Home | History | Annotate | Download | only in coding
      1 .. _nacl_io:
      2 
      3 ###################
      4 The nacl_io Library
      5 ###################
      6 
      7 .. contents::
      8   :local:
      9   :backlinks: none
     10   :depth: 2
     11 
     12 Introduction
     13 ============
     14 
     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.
     20 
     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``.
     33 
     34 As well as the HTML5 file system, nacl_io provides several other file system
     35 types which are described in the table below:
     36 
     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 =========== ==================================================================
     45 
     46 Using nacl_io
     47 =============
     48 
     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:
     53 
     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.
     67 
     68 The nacl_io demo
     69 ================
     70 
     71 Building and running the demo
     72 -----------------------------
     73 
     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:
     76 
     77 .. image:: /images/nacl_io1.png
     78 
     79 Follow these steps to build and run the demo:
     80 
     81 * Open a terminal in the demo directory::
     82 
     83     $ cd $NACL_SDK_ROOT/examples/demo/nacl_io_demo
     84 
     85 * run the demo::
     86 
     87     $ make run
     88 
     89 Once the demo is running, try these operations:
     90 
     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
    105 
    106 A look at the code
    107 ------------------
    108 
    109 The demo is written C and comprises three files.
    110 
    111 nacl_io_demo.c
    112 ^^^^^^^^^^^^^^
    113 
    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``.
    117 
    118 .. naclcode::
    119 
    120   static PP_Bool Instance_DidCreate(PP_Instance instance,
    121                                     uint32_t argc,
    122                                     const char* argn[],
    123                                     const char* argv[]) {
    124     g_instance = instance;
    125     nacl_io_init_ppapi(instance, get_browser_interface);
    126     mount(
    127         "",  /* source */
    128         "/persistent",  /* target */
    129         "html5fs",  /* filesystemtype */
    130         0,  /* mountflags */
    131         "type=PERSISTENT,expected_size=1048576");  /* data specific to the html5fs type */
    132 
    133     pthread_create(&g_handle_message_thread, NULL, &HandleMessageThread, NULL);
    134     InitializeMessageQueue();
    135 
    136     return PP_TRUE;
    137   }
    138 
    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``):
    143 
    144 .. naclcode::
    145 
    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 
    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,
    160 described below.
    161 
    162 queue.c
    163 ^^^^^^^
    164 
    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``.
    170 
    171 handlers.c
    172 ^^^^^^^^^^
    173 
    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
    180 "ordinary" C code.
    181 
    182 
    183 .. naclcode::
    184 
    185   int HandleFwrite(int num_params, char** params, char** output) {
    186     FILE* file;
    187     const char* file_index_string;
    188     const char* data;
    189     size_t data_len;
    190     size_t bytes_written;
    191 
    192     if (num_params != 2) {
    193       *output = PrintfToNewString("Error: fwrite takes 2 parameters.");
    194       return 1;
    195     }
    196 
    197     file_index_string = params[0];
    198     file = GetFileFromIndexString(file_index_string, NULL);
    199     data = params[1];
    200     data_len = strlen(data);
    201 
    202     if (!file) {
    203       *output = PrintfToNewString("Error: Unknown file handle %s.",
    204                                   file_index_string);
    205       return 2;
    206     }
    207 
    208     bytes_written = fwrite(data, 1, data_len, file);
    209 
    210     *output = PrintfToNewString("fwrite\1%s\1%d", file_index_string,
    211                                 bytes_written);
    212     return 0;
    213   }
    214 
    215 Reference information
    216 =====================
    217 
    218 The example discussed here is included in the SDK in the directory
    219 ``examples/demo/nacl_io_demo``.
    220 
    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``.
    225 
    226 For more about the HTML5 file system read the `specification
    227 <http://dev.w3.org/2009/dap/file-system/pub/FileSystem/>`_.
    228