15 ``nacl_io`` is a utility library that provides implementations of standard
16 C APIs such as POSIX I/O (``stdio.h``) and BSD sockets (``sys/socket.h``).
17 Its primary function is to allow code that uses these standard APIs to be
18 compiled and used in a Native Client module. The library is included as part
19 of Native Client SDK and is implemented in on top of Pepper API.
21 Since Native Client modules cannot access the host machine's file system
22 directly, nacl_io provides several alternative filesystem types which
23 can be used by the application. For example, the Chrome browser supports the
24 `HTML5 File System API
25 <http://www.html5rocks.com/en/tutorials/file/filesystem/>`_ which provides
26 access to a protected area of the local file system. This filesystem can
27 be accessed by an HTML page using JavaScript commands, and also by a Native
28 Client module using the Pepper :doc:`File IO API <file-io>`. With nacl_io
29 a Native Client application can mount an HTML5 filesystem and access it via
30 standard POSIX I/O function such as ``fopen``, ``fseek``, ``fread``,
31 ``fwrite``, and ``fclose``, or their low level UNIX counterparts ``open``,
32 ``lseek``, ``read``, ``write`` and ``close``.
34 As well as the HTML5 file system, nacl_io provides several other file system
35 types which are described in the table below:
37 =========== ==================================================================
38 File System Description
39 =========== ==================================================================
40 memfs An in-memory file system
41 html5fs An HTML5 local file system, which can be persistent or temporary
42 http Maps files on a remote webserver into the local filesystem.
43 dev A file system containing special files (e.g.: ``/dev/null``)
44 =========== ==================================================================
49 Using nacl_io is mostly just a matter of using the standard POSIX C library
50 functions. However, there are some steps required to initialize the library
51 and setup the filesystem mounts. In general the following steps will be needed
52 to use nacl_io in a NaCl application:
54 #. Link the application with the nacl_io library (``-lnacl_io``)
55 #. Initialize nacl_io at startup using the ``nacl_io_init_ppapi`` or
56 ``nacl_io_init`` functions.
57 #. Mount any desired filesystems using the ``mount`` function. The arguments
58 to ``mount`` for the different filesystem types are detailed in
59 ``include/nacl_io/nacl_io.h``.
60 #. If you are going to mount an HTML5 file system, be sure to allocate space
61 for it. You can either set the ``unlimitedStorage`` permission in the app's
62 Web Store manifest file, or call the HTML5 QuotaManagement API. These
63 options are explained in the :ref:`File IO documentation <quota_management>`.
64 #. Make sure that file and socket API calls are all made from the background
65 thread. This is because the main Pepper thread does not support the blocking
66 behavior needed by the POSIX I/O operations.
71 Building and running the demo
72 -----------------------------
74 The demo application launches a Native Client module that mounts three file
75 systems and displays a set of controls that let you work with them:
77 .. image:: /images/nacl_io1.png
79 Follow these steps to build and run the demo:
81 * Open a terminal in the demo directory::
83 $ cd $NACL_SDK_ROOT/examples/demo/nacl_io
89 Once the demo is running, try these operations:
91 #. select the fopen command (when you select a command the fields in the line
92 below will change according to the command)
93 #. type in the filename ``/persistent/test``
94 #. check the write checkbox and press the fopen button
95 #. select the fwrite command and select the file ``/persistent/test`` in the
96 menu that appears below on the left
97 #. enter some data and press the fwrite button
98 #. select the fclose command, be sure the file ``/persistent/test`` is selected
99 in the menu, and press the fclose button
100 #. select the fopen command
101 #. type in the filename ``/persistent/test``
102 #. check the fread checkbox and press the fopen button
103 #. select the fread command, be sure the file /persistent/test is selected in
104 the menu, enter a byte count, and press the fread button
109 The demo is written C and comprises three files.
114 This is the demo's main file. The code here creates and initializes the Native
115 Client module instance. The Pepper function ``Instance_DidCreate`` initializes
116 nacl_io and mounts an HTML5 filesystem at ``/persistent``.
120 static PP_Bool Instance_DidCreate(PP_Instance instance,
123 const char* argv[]) {
124 g_instance = instance;
125 nacl_io_init_ppapi(instance, get_browser_interface);
128 "/persistent", /* target */
129 "html5fs", /* filesystemtype */
131 "type=PERSISTENT,expected_size=1048576"); /* data specific to the html5fs type */
133 pthread_create(&g_handle_message_thread, NULL, &HandleMessageThread, NULL);
134 InitializeMessageQueue();
139 Space is allocated to the ``/persistent`` file system after the module is
140 initialized. This is accomplished by the ``domContentLoaded`` function in
141 the file ``example.js``. This script is included in the module's html page (see
142 ``examples/demo/index.html``):
146 function domContentLoaded(name, tc, config, width, height) {
147 navigator.webkitPersistentStorage.requestQuota(window.PERSISTENT, 1024 * 1024,
150 'Allocated ' + bytes + ' bytes of persistant storage.');
151 common.createNaClModule(name, tc, config, width, height);
152 common.attachDefaultListeners();
154 function(e) { alert('Failed to allocate space') });
157 The ``Instance_DidCreate`` 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,
165 This file implements a circular queue that is used to receive messages from the
166 browser UI to the Native Client module. The file system commands in the
167 enqueued messages are executed on the worker thread. This keeps blocking calls
168 (like fread) off the main Native Client thread, which is a good thing. The
169 queue is initialized in nacl_io_demo.c ``Instance_DidCreate``.
174 This file implements the stdio calls associated with the commands sent from the
175 browser. There is a separate ``Handle*`` function for each command: fopen,
176 fclose, fseek, fread, fwrite. The handlers are called from the
177 ``HandleMessage`` function in nacl_io_demo.c, which runs in the worker
178 thread managing the message queue. The code for the ``fwrite`` handler appears
179 below. Notice that it does not contain any PPAPI calls and looks like
185 int HandleFwrite(int num_params, char** params, char** output) {
187 const char* file_index_string;
190 size_t bytes_written;
192 if (num_params != 2) {
193 *output = PrintfToNewString("Error: fwrite takes 2 parameters.");
197 file_index_string = params[0];
198 file = GetFileFromIndexString(file_index_string, NULL);
200 data_len = strlen(data);
203 *output = PrintfToNewString("Error: Unknown file handle %s.",
208 bytes_written = fwrite(data, 1, data_len, file);
210 *output = PrintfToNewString("fwrite\1%s\1%d", file_index_string,
215 Reference information
216 =====================
218 The example discussed here is included in the SDK in the directory
219 ``examples/demo/nacl_io``.
221 The nacl_io library is included in the SDK toolchain and is not a part of the
222 Pepper API. For reference information related to the nacl_io interface see
223 its header file in the SDK directory, located at
224 ``include/nacl_io/nacl_io.h``.
226 For more about the HTML5 file system read the `specification
227 <http://dev.w3.org/2009/dap/file-system/pub/FileSystem/>`_.