1 {{+bindTo:partials.standard_nacl_article}} 2 3 <section id="the-nacl-io-library"> 4 <span id="nacl-io"></span><h1 id="the-nacl-io-library"><span id="nacl-io"></span>The nacl_io Library</h1> 5 <div class="contents local" id="contents" style="display: none"> 6 <ul class="small-gap"> 7 <li><a class="reference internal" href="#introduction" id="id1">Introduction</a></li> 8 <li><a class="reference internal" href="#using-nacl-io" id="id2">Using nacl_io</a></li> 9 <li><p class="first"><a class="reference internal" href="#the-nacl-io-demo" id="id3">The nacl_io demo</a></p> 10 <ul class="small-gap"> 11 <li><a class="reference internal" href="#building-and-running-the-demo" id="id4">Building and running the demo</a></li> 12 <li><a class="reference internal" href="#a-look-at-the-code" id="id5">A look at the code</a></li> 13 </ul> 14 </li> 15 <li><a class="reference internal" href="#reference-information" id="id6">Reference information</a></li> 16 </ul> 17 18 </div><h2 id="introduction">Introduction</h2> 19 <p><code>nacl_io</code> is a utility library that provides implementations of standard 20 C APIs such as POSIX I/O (<code>stdio.h</code>) and BSD sockets (<code>sys/socket.h</code>). 21 Its primary function is to allow code that uses these standard APIs to be 22 compiled and used in a Native Client module. The library is included as part 23 of Native Client SDK and is implemented in on top of Pepper API.</p> 24 <p>Since Native Client modules cannot access the host machine’s file system 25 directly, nacl_io provides several alternative filesystem types which 26 can be used by the application. For example, the Chrome browser supports the 27 <a class="reference external" href="http://www.html5rocks.com/en/tutorials/file/filesystem/">HTML5 File System API</a> which provides 28 access to a protected area of the local file system. This filesystem can 29 be accessed by an HTML page using JavaScript commands, and also by a Native 30 Client module using the Pepper <a class="reference internal" href="/native-client/devguide/coding/file-io.html"><em>File IO API</em></a>. With nacl_io 31 a Native Client application can mount an HTML5 filesystem and access it via 32 standard POSIX I/O function such as <code>fopen</code>, <code>fseek</code>, <code>fread</code>, 33 <code>fwrite</code>, and <code>fclose</code>, or their low level UNIX counterparts <code>open</code>, 34 <code>lseek</code>, <code>read</code>, <code>write</code> and <code>close</code>.</p> 35 <p>As well as the HTML5 file system, nacl_io provides several other file system 36 types which are described in the table below:</p> 37 <table border="1" class="docutils"> 38 <colgroup> 39 </colgroup> 40 <thead valign="bottom"> 41 <tr class="row-odd"><th class="head">File System</th> 42 <th class="head">Description</th> 43 </tr> 44 </thead> 45 <tbody valign="top"> 46 <tr class="row-even"><td>memfs</td> 47 <td>An in-memory file system</td> 48 </tr> 49 <tr class="row-odd"><td>html5fs</td> 50 <td>An HTML5 local file system, which can be persistent or temporary</td> 51 </tr> 52 <tr class="row-even"><td>http</td> 53 <td>Maps files on a remote webserver into the local filesystem.</td> 54 </tr> 55 <tr class="row-odd"><td>dev</td> 56 <td>A file system containing special files (e.g.: <code>/dev/null</code>)</td> 57 </tr> 58 </tbody> 59 </table> 60 <h2 id="using-nacl-io">Using nacl_io</h2> 61 <p>Using nacl_io is mostly just a matter of using the standard POSIX C library 62 functions. However, there are some steps required to initialize the library 63 and setup the filesystem mounts. In general the following steps will be needed 64 to use nacl_io in a NaCl application:</p> 65 <ol class="arabic simple"> 66 <li>Link the application with the nacl_io library (<code>-lnacl_io</code>)</li> 67 <li>Initialize nacl_io at startup using the <code>nacl_io_init_ppapi</code> or 68 <code>nacl_io_init</code> functions.</li> 69 <li>Mount any desired filesystems using the <code>mount</code> function. The arguments 70 to <code>mount</code> for the different filesystem types are detailed in 71 <code>include/nacl_io/nacl_io.h</code>.</li> 72 <li>If you are going to mount an HTML5 file system, be sure to allocate space 73 for it. You can either set the <code>unlimitedStorage</code> permission in the app’s 74 Web Store manifest file, or call the HTML5 QuotaManagement API. These 75 options are explained in the <a class="reference internal" href="/native-client/devguide/coding/file-io.html#quota-management"><em>File IO documentation</em></a>.</li> 76 <li>Make sure that file and socket API calls are all made from the background 77 thread. This is because the main Pepper thread does not support the blocking 78 behavior needed by the POSIX I/O operations.</li> 79 </ol> 80 <h2 id="the-nacl-io-demo">The nacl_io demo</h2> 81 <h3 id="building-and-running-the-demo">Building and running the demo</h3> 82 <p>The demo application launches a Native Client module that mounts three file 83 systems and displays a set of controls that let you work with them:</p> 84 <img alt="/native-client/images/nacl_io1.png" src="/native-client/images/nacl_io1.png" /> 85 <p>Follow these steps to build and run the demo:</p> 86 <ul class="small-gap"> 87 <li><p class="first">Open a terminal in the demo directory:</p> 88 <pre class="prettyprint"> 89 $ cd $NACL_SDK_ROOT/examples/demo/nacl_io_demo 90 </pre> 91 </li> 92 <li><p class="first">run the demo:</p> 93 <pre class="prettyprint"> 94 $ make run 95 </pre> 96 </li> 97 </ul> 98 <p>Once the demo is running, try these operations:</p> 99 <ol class="arabic simple"> 100 <li>select the fopen command (when you select a command the fields in the line 101 below will change according to the command)</li> 102 <li>type in the filename <code>/persistent/test</code></li> 103 <li>check the write checkbox and press the fopen button</li> 104 <li>select the fwrite command and select the file <code>/persistent/test</code> in the 105 menu that appears below on the left</li> 106 <li>enter some data and press the fwrite button</li> 107 <li>select the fclose command, be sure the file <code>/persistent/test</code> is selected 108 in the menu, and press the fclose button</li> 109 <li>select the fopen command</li> 110 <li>type in the filename <code>/persistent/test</code></li> 111 <li>check the fread checkbox and press the fopen button</li> 112 <li>select the fread command, be sure the file /persistent/test is selected in 113 the menu, enter a byte count, and press the fread button</li> 114 </ol> 115 <h3 id="a-look-at-the-code">A look at the code</h3> 116 <p>The demo is written C and comprises three files.</p> 117 <h4 id="nacl-io-demo-c">nacl_io_demo.c</h4> 118 <p>This is the demo’s main file. The code here creates and initializes the Native 119 Client module instance. The Pepper function <code>Instance_DidCreate</code> initializes 120 nacl_io and mounts an HTML5 filesystem at <code>/persistent</code>.</p> 121 <pre class="prettyprint"> 122 static PP_Bool Instance_DidCreate(PP_Instance instance, 123 uint32_t argc, 124 const char* argn[], 125 const char* argv[]) { 126 g_instance = instance; 127 nacl_io_init_ppapi(instance, get_browser_interface); 128 mount( 129 "", /* source */ 130 "/persistent", /* target */ 131 "html5fs", /* filesystemtype */ 132 0, /* mountflags */ 133 "type=PERSISTENT,expected_size=1048576"); /* data specific to the html5fs type */ 134 135 pthread_create(&g_handle_message_thread, NULL, &HandleMessageThread, NULL); 136 InitializeMessageQueue(); 137 138 return PP_TRUE; 139 } 140 </pre> 141 <p>Space is allocated to the <code>/persistent</code> file system after the module is 142 initialized. This is accomplished by the <code>domContentLoaded</code> function in 143 the file <code>example.js</code>. This script is included in the module’s html page (see 144 <code>examples/demo/index.html</code>):</p> 145 <pre class="prettyprint"> 146 function domContentLoaded(name, tc, config, width, height) { 147 navigator.webkitPersistentStorage.requestQuota(window.PERSISTENT, 1024 * 1024, 148 function(bytes) { 149 common.updateStatus( 150 'Allocated ' + bytes + ' bytes of persistant storage.'); 151 common.createNaClModule(name, tc, config, width, height); 152 common.attachDefaultListeners(); 153 }, 154 function(e) { alert('Failed to allocate space') }); 155 } 156 </pre> 157 <p>The <code>Instance_DidCreate</code> function also creates a worker thread that receives 158 messages sent from the html page and performs the specified file system 159 operations. The logic for the worker thread is encoded in the other two files, 160 described below.</p> 161 <h4 id="queue-c">queue.c</h4> 162 <p>This file implements a circular queue that is used to receive messages from the 163 browser UI to the Native Client module. The file system commands in the 164 enqueued messages are executed on the worker thread. This keeps blocking calls 165 (like fread) off the main Native Client thread, which is a good thing. The 166 queue is initialized in nacl_io_demo.c <code>Instance_DidCreate</code>.</p> 167 <h4 id="handlers-c">handlers.c</h4> 168 <p>This file implements the stdio calls associated with the commands sent from the 169 browser. There is a separate <code>Handle*</code> function for each command: fopen, 170 fclose, fseek, fread, fwrite. The handlers are called from the 171 <code>HandleMessage</code> function in nacl_io_demo.c, which runs in the worker 172 thread managing the message queue. The code for the <code>fwrite</code> handler appears 173 below. Notice that it does not contain any PPAPI calls and looks like 174 “ordinary” C code.</p> 175 <pre class="prettyprint"> 176 int HandleFwrite(int num_params, char** params, char** output) { 177 FILE* file; 178 const char* file_index_string; 179 const char* data; 180 size_t data_len; 181 size_t bytes_written; 182 183 if (num_params != 2) { 184 *output = PrintfToNewString("Error: fwrite takes 2 parameters."); 185 return 1; 186 } 187 188 file_index_string = params[0]; 189 file = GetFileFromIndexString(file_index_string, NULL); 190 data = params[1]; 191 data_len = strlen(data); 192 193 if (!file) { 194 *output = PrintfToNewString("Error: Unknown file handle %s.", 195 file_index_string); 196 return 2; 197 } 198 199 bytes_written = fwrite(data, 1, data_len, file); 200 201 *output = PrintfToNewString("fwrite\1%s\1%d", file_index_string, 202 bytes_written); 203 return 0; 204 } 205 </pre> 206 <h2 id="reference-information">Reference information</h2> 207 <p>The example discussed here is included in the SDK in the directory 208 <code>examples/demo/nacl_io_demo</code>.</p> 209 <p>The nacl_io library is included in the SDK toolchain and is not a part of the 210 Pepper API. For reference information related to the nacl_io interface see 211 its header file in the SDK directory, located at 212 <code>include/nacl_io/nacl_io.h</code>.</p> 213 <p>For more about the HTML5 file system read the <a class="reference external" href="http://dev.w3.org/2009/dap/file-system/pub/FileSystem/">specification</a>.</p> 214 </section> 215 216 {{/partials.standard_nacl_article}} 217