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