10e552da7SchristosFilesystem 20e552da7Schristos========== 30e552da7Schristos 40e552da7SchristosSimple filesystem read/write is achieved using the ``uv_fs_*`` functions and the 50e552da7Schristos``uv_fs_t`` struct. 60e552da7Schristos 70e552da7Schristos.. note:: 80e552da7Schristos 90e552da7Schristos The libuv filesystem operations are different from :doc:`socket operations 100e552da7Schristos <networking>`. Socket operations use the non-blocking operations provided 110e552da7Schristos by the operating system. Filesystem operations use blocking functions 120e552da7Schristos internally, but invoke these functions in a `thread pool`_ and notify 130e552da7Schristos watchers registered with the event loop when application interaction is 140e552da7Schristos required. 150e552da7Schristos 16*5f2f4271Schristos.. _thread pool: https://docs.libuv.org/en/v1.x/threadpool.html#thread-pool-work-scheduling 170e552da7Schristos 180e552da7SchristosAll filesystem functions have two forms - *synchronous* and *asynchronous*. 190e552da7Schristos 200e552da7SchristosThe *synchronous* forms automatically get called (and **block**) if the 210e552da7Schristoscallback is null. The return value of functions is a :ref:`libuv error code 220e552da7Schristos<libuv-error-handling>`. This is usually only useful for synchronous calls. 230e552da7SchristosThe *asynchronous* form is called when a callback is passed and the return 240e552da7Schristosvalue is 0. 250e552da7Schristos 260e552da7SchristosReading/Writing files 270e552da7Schristos--------------------- 280e552da7Schristos 290e552da7SchristosA file descriptor is obtained using 300e552da7Schristos 310e552da7Schristos.. code-block:: c 320e552da7Schristos 330e552da7Schristos int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb) 340e552da7Schristos 350e552da7Schristos``flags`` and ``mode`` are standard 36*5f2f4271Schristos`Unix flags <https://man7.org/linux/man-pages/man2/open.2.html>`_. 370e552da7Schristoslibuv takes care of converting to the appropriate Windows flags. 380e552da7Schristos 390e552da7SchristosFile descriptors are closed using 400e552da7Schristos 410e552da7Schristos.. code-block:: c 420e552da7Schristos 430e552da7Schristos int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb) 440e552da7Schristos 450e552da7Schristos 460e552da7SchristosFilesystem operation callbacks have the signature: 470e552da7Schristos 480e552da7Schristos.. code-block:: c 490e552da7Schristos 500e552da7Schristos void callback(uv_fs_t* req); 510e552da7Schristos 520e552da7SchristosLet's see a simple implementation of ``cat``. We start with registering 530e552da7Schristosa callback for when the file is opened: 540e552da7Schristos 550e552da7Schristos.. rubric:: uvcat/main.c - opening a file 560e552da7Schristos.. literalinclude:: ../../code/uvcat/main.c 57*5f2f4271Schristos :language: c 580e552da7Schristos :linenos: 590e552da7Schristos :lines: 41-53 600e552da7Schristos :emphasize-lines: 4, 6-7 610e552da7Schristos 620e552da7SchristosThe ``result`` field of a ``uv_fs_t`` is the file descriptor in case of the 630e552da7Schristos``uv_fs_open`` callback. If the file is successfully opened, we start reading it. 640e552da7Schristos 650e552da7Schristos.. rubric:: uvcat/main.c - read callback 660e552da7Schristos.. literalinclude:: ../../code/uvcat/main.c 67*5f2f4271Schristos :language: c 680e552da7Schristos :linenos: 69*5f2f4271Schristos :lines: 26-39 700e552da7Schristos :emphasize-lines: 2,8,12 710e552da7Schristos 720e552da7SchristosIn the case of a read call, you should pass an *initialized* buffer which will 730e552da7Schristosbe filled with data before the read callback is triggered. The ``uv_fs_*`` 740e552da7Schristosoperations map almost directly to certain POSIX functions, so EOF is indicated 750e552da7Schristosin this case by ``result`` being 0. In the case of streams or pipes, the 760e552da7Schristos``UV_EOF`` constant would have been passed as a status instead. 770e552da7Schristos 780e552da7SchristosHere you see a common pattern when writing asynchronous programs. The 790e552da7Schristos``uv_fs_close()`` call is performed synchronously. *Usually tasks which are 800e552da7Schristosone-off, or are done as part of the startup or shutdown stage are performed 810e552da7Schristossynchronously, since we are interested in fast I/O when the program is going 820e552da7Schristosabout its primary task and dealing with multiple I/O sources*. For solo tasks 830e552da7Schristosthe performance difference usually is negligible and may lead to simpler code. 840e552da7Schristos 850e552da7SchristosFilesystem writing is similarly simple using ``uv_fs_write()``. *Your callback 860e552da7Schristoswill be triggered after the write is complete*. In our case the callback 870e552da7Schristossimply drives the next read. Thus read and write proceed in lockstep via 880e552da7Schristoscallbacks. 890e552da7Schristos 900e552da7Schristos.. rubric:: uvcat/main.c - write callback 910e552da7Schristos.. literalinclude:: ../../code/uvcat/main.c 92*5f2f4271Schristos :language: c 930e552da7Schristos :linenos: 94*5f2f4271Schristos :lines: 17-24 950e552da7Schristos :emphasize-lines: 6 960e552da7Schristos 970e552da7Schristos.. warning:: 980e552da7Schristos 990e552da7Schristos Due to the way filesystems and disk drives are configured for performance, 1000e552da7Schristos a write that 'succeeds' may not be committed to disk yet. 1010e552da7Schristos 1020e552da7SchristosWe set the dominos rolling in ``main()``: 1030e552da7Schristos 1040e552da7Schristos.. rubric:: uvcat/main.c 1050e552da7Schristos.. literalinclude:: ../../code/uvcat/main.c 106*5f2f4271Schristos :language: c 1070e552da7Schristos :linenos: 1080e552da7Schristos :lines: 55- 1090e552da7Schristos :emphasize-lines: 2 1100e552da7Schristos 1110e552da7Schristos.. warning:: 1120e552da7Schristos 1130e552da7Schristos The ``uv_fs_req_cleanup()`` function must always be called on filesystem 1140e552da7Schristos requests to free internal memory allocations in libuv. 1150e552da7Schristos 1160e552da7SchristosFilesystem operations 1170e552da7Schristos--------------------- 1180e552da7Schristos 1190e552da7SchristosAll the standard filesystem operations like ``unlink``, ``rmdir``, ``stat`` are 1200e552da7Schristossupported asynchronously and have intuitive argument order. They follow the 1210e552da7Schristossame patterns as the read/write/open calls, returning the result in the 1220e552da7Schristos``uv_fs_t.result`` field. The full list: 1230e552da7Schristos 1240e552da7Schristos.. rubric:: Filesystem operations 1250e552da7Schristos.. code-block:: c 1260e552da7Schristos 1270e552da7Schristos int uv_fs_close(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); 1280e552da7Schristos int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int mode, uv_fs_cb cb); 1290e552da7Schristos int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb); 1300e552da7Schristos int uv_fs_unlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); 1310e552da7Schristos int uv_fs_write(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb); 1320e552da7Schristos int uv_fs_copyfile(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb); 1330e552da7Schristos int uv_fs_mkdir(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); 1340e552da7Schristos int uv_fs_mkdtemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb); 135*5f2f4271Schristos int uv_fs_mkstemp(uv_loop_t* loop, uv_fs_t* req, const char* tpl, uv_fs_cb cb); 1360e552da7Schristos int uv_fs_rmdir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); 1370e552da7Schristos int uv_fs_scandir(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, uv_fs_cb cb); 1380e552da7Schristos int uv_fs_scandir_next(uv_fs_t* req, uv_dirent_t* ent); 1390e552da7Schristos int uv_fs_opendir(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); 1400e552da7Schristos int uv_fs_readdir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb); 1410e552da7Schristos int uv_fs_closedir(uv_loop_t* loop, uv_fs_t* req, uv_dir_t* dir, uv_fs_cb cb); 1420e552da7Schristos int uv_fs_stat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); 1430e552da7Schristos int uv_fs_fstat(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); 1440e552da7Schristos int uv_fs_rename(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); 1450e552da7Schristos int uv_fs_fsync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); 1460e552da7Schristos int uv_fs_fdatasync(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_fs_cb cb); 1470e552da7Schristos int uv_fs_ftruncate(uv_loop_t* loop, uv_fs_t* req, uv_file file, int64_t offset, uv_fs_cb cb); 1480e552da7Schristos int uv_fs_sendfile(uv_loop_t* loop, uv_fs_t* req, uv_file out_fd, uv_file in_fd, int64_t in_offset, size_t length, uv_fs_cb cb); 1490e552da7Schristos int uv_fs_access(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); 1500e552da7Schristos int uv_fs_chmod(uv_loop_t* loop, uv_fs_t* req, const char* path, int mode, uv_fs_cb cb); 1510e552da7Schristos int uv_fs_utime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb); 1520e552da7Schristos int uv_fs_futime(uv_loop_t* loop, uv_fs_t* req, uv_file file, double atime, double mtime, uv_fs_cb cb); 153*5f2f4271Schristos int uv_fs_lutime(uv_loop_t* loop, uv_fs_t* req, const char* path, double atime, double mtime, uv_fs_cb cb); 1540e552da7Schristos int uv_fs_lstat(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); 1550e552da7Schristos int uv_fs_link(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, uv_fs_cb cb); 1560e552da7Schristos int uv_fs_symlink(uv_loop_t* loop, uv_fs_t* req, const char* path, const char* new_path, int flags, uv_fs_cb cb); 1570e552da7Schristos int uv_fs_readlink(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); 1580e552da7Schristos int uv_fs_realpath(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); 1590e552da7Schristos int uv_fs_fchmod(uv_loop_t* loop, uv_fs_t* req, uv_file file, int mode, uv_fs_cb cb); 1600e552da7Schristos int uv_fs_chown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); 1610e552da7Schristos int uv_fs_fchown(uv_loop_t* loop, uv_fs_t* req, uv_file file, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); 1620e552da7Schristos int uv_fs_lchown(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_uid_t uid, uv_gid_t gid, uv_fs_cb cb); 163*5f2f4271Schristos int uv_fs_statfs(uv_loop_t* loop, uv_fs_t* req, const char* path, uv_fs_cb cb); 1640e552da7Schristos 1650e552da7Schristos 1660e552da7Schristos.. _buffers-and-streams: 1670e552da7Schristos 1680e552da7SchristosBuffers and Streams 1690e552da7Schristos------------------- 1700e552da7Schristos 1710e552da7SchristosThe basic I/O handle in libuv is the stream (``uv_stream_t``). TCP sockets, UDP 1720e552da7Schristossockets, and pipes for file I/O and IPC are all treated as stream subclasses. 1730e552da7Schristos 1740e552da7SchristosStreams are initialized using custom functions for each subclass, then operated 1750e552da7Schristosupon using 1760e552da7Schristos 1770e552da7Schristos.. code-block:: c 1780e552da7Schristos 1790e552da7Schristos int uv_read_start(uv_stream_t*, uv_alloc_cb alloc_cb, uv_read_cb read_cb); 1800e552da7Schristos int uv_read_stop(uv_stream_t*); 1810e552da7Schristos int uv_write(uv_write_t* req, uv_stream_t* handle, 1820e552da7Schristos const uv_buf_t bufs[], unsigned int nbufs, uv_write_cb cb); 1830e552da7Schristos 1840e552da7SchristosThe stream based functions are simpler to use than the filesystem ones and 1850e552da7Schristoslibuv will automatically keep reading from a stream when ``uv_read_start()`` is 1860e552da7Schristoscalled once, until ``uv_read_stop()`` is called. 1870e552da7Schristos 1880e552da7SchristosThe discrete unit of data is the buffer -- ``uv_buf_t``. This is simply 1890e552da7Schristosa collection of a pointer to bytes (``uv_buf_t.base``) and the length 1900e552da7Schristos(``uv_buf_t.len``). The ``uv_buf_t`` is lightweight and passed around by value. 1910e552da7SchristosWhat does require management is the actual bytes, which have to be allocated 1920e552da7Schristosand freed by the application. 1930e552da7Schristos 1940e552da7Schristos.. ERROR:: 1950e552da7Schristos 196*5f2f4271Schristos **THIS PROGRAM DOES NOT ALWAYS WORK, NEED SOMETHING BETTER** 1970e552da7Schristos 1980e552da7SchristosTo demonstrate streams we will need to use ``uv_pipe_t``. This allows streaming 1990e552da7Schristoslocal files [#]_. Here is a simple tee utility using libuv. Doing all operations 2000e552da7Schristosasynchronously shows the power of evented I/O. The two writes won't block each 2010e552da7Schristosother, but we have to be careful to copy over the buffer data to ensure we don't 2020e552da7Schristosfree a buffer until it has been written. 2030e552da7Schristos 2040e552da7SchristosThe program is to be executed as:: 2050e552da7Schristos 2060e552da7Schristos ./uvtee <output_file> 2070e552da7Schristos 2080e552da7SchristosWe start off opening pipes on the files we require. libuv pipes to a file are 2090e552da7Schristosopened as bidirectional by default. 2100e552da7Schristos 2110e552da7Schristos.. rubric:: uvtee/main.c - read on pipes 2120e552da7Schristos.. literalinclude:: ../../code/uvtee/main.c 213*5f2f4271Schristos :language: c 2140e552da7Schristos :linenos: 215*5f2f4271Schristos :lines: 62-80 2160e552da7Schristos :emphasize-lines: 4,5,15 2170e552da7Schristos 2180e552da7SchristosThe third argument of ``uv_pipe_init()`` should be set to 1 for IPC using named 2190e552da7Schristospipes. This is covered in :doc:`processes`. The ``uv_pipe_open()`` call 2200e552da7Schristosassociates the pipe with the file descriptor, in this case ``0`` (standard 2210e552da7Schristosinput). 2220e552da7Schristos 2230e552da7SchristosWe start monitoring ``stdin``. The ``alloc_buffer`` callback is invoked as new 2240e552da7Schristosbuffers are required to hold incoming data. ``read_stdin`` will be called with 2250e552da7Schristosthese buffers. 2260e552da7Schristos 2270e552da7Schristos.. rubric:: uvtee/main.c - reading buffers 2280e552da7Schristos.. literalinclude:: ../../code/uvtee/main.c 229*5f2f4271Schristos :language: c 2300e552da7Schristos :linenos: 2310e552da7Schristos :lines: 19-22,44-60 2320e552da7Schristos 2330e552da7SchristosThe standard ``malloc`` is sufficient here, but you can use any memory allocation 2340e552da7Schristosscheme. For example, node.js uses its own slab allocator which associates 2350e552da7Schristosbuffers with V8 objects. 2360e552da7Schristos 2370e552da7SchristosThe read callback ``nread`` parameter is less than 0 on any error. This error 2380e552da7Schristosmight be EOF, in which case we close all the streams, using the generic close 2390e552da7Schristosfunction ``uv_close()`` which deals with the handle based on its internal type. 2400e552da7SchristosOtherwise ``nread`` is a non-negative number and we can attempt to write that 2410e552da7Schristosmany bytes to the output streams. Finally remember that buffer allocation and 2420e552da7Schristosdeallocation is application responsibility, so we free the data. 2430e552da7Schristos 2440e552da7SchristosThe allocation callback may return a buffer with length zero if it fails to 2450e552da7Schristosallocate memory. In this case, the read callback is invoked with error 2460e552da7SchristosUV_ENOBUFS. libuv will continue to attempt to read the stream though, so you 2470e552da7Schristosmust explicitly call ``uv_close()`` if you want to stop when allocation fails. 2480e552da7Schristos 2490e552da7SchristosThe read callback may be called with ``nread = 0``, indicating that at this 2500e552da7Schristospoint there is nothing to be read. Most applications will just ignore this. 2510e552da7Schristos 2520e552da7Schristos.. rubric:: uvtee/main.c - Write to pipe 2530e552da7Schristos.. literalinclude:: ../../code/uvtee/main.c 254*5f2f4271Schristos :language: c 2550e552da7Schristos :linenos: 2560e552da7Schristos :lines: 9-13,23-42 2570e552da7Schristos 2580e552da7Schristos``write_data()`` makes a copy of the buffer obtained from read. This buffer 2590e552da7Schristosdoes not get passed through to the write callback trigged on write completion. To 2600e552da7Schristosget around this we wrap a write request and a buffer in ``write_req_t`` and 2610e552da7Schristosunwrap it in the callbacks. We make a copy so we can free the two buffers from 2620e552da7Schristosthe two calls to ``write_data`` independently of each other. While acceptable 2630e552da7Schristosfor a demo program like this, you'll probably want smarter memory management, 2640e552da7Schristoslike reference counted buffers or a pool of buffers in any major application. 2650e552da7Schristos 2660e552da7Schristos.. WARNING:: 2670e552da7Schristos 2680e552da7Schristos If your program is meant to be used with other programs it may knowingly or 2690e552da7Schristos unknowingly be writing to a pipe. This makes it susceptible to `aborting on 2700e552da7Schristos receiving a SIGPIPE`_. It is a good idea to insert:: 2710e552da7Schristos 2720e552da7Schristos signal(SIGPIPE, SIG_IGN) 2730e552da7Schristos 2740e552da7Schristos in the initialization stages of your application. 2750e552da7Schristos 2760e552da7Schristos.. _aborting on receiving a SIGPIPE: http://pod.tst.eu/http://cvs.schmorp.de/libev/ev.pod#The_special_problem_of_SIGPIPE 2770e552da7Schristos 2780e552da7SchristosFile change events 2790e552da7Schristos------------------ 2800e552da7Schristos 2810e552da7SchristosAll modern operating systems provide APIs to put watches on individual files or 2820e552da7Schristosdirectories and be informed when the files are modified. libuv wraps common 2830e552da7Schristosfile change notification libraries [#fsnotify]_. This is one of the more 2840e552da7Schristosinconsistent parts of libuv. File change notification systems are themselves 2850e552da7Schristosextremely varied across platforms so getting everything working everywhere is 2860e552da7Schristosdifficult. To demonstrate, I'm going to build a simple utility which runs 2870e552da7Schristosa command whenever any of the watched files change:: 2880e552da7Schristos 2890e552da7Schristos ./onchange <command> <file1> [file2] ... 2900e552da7Schristos 291*5f2f4271Schristos.. note:: 292*5f2f4271Schristos 293*5f2f4271Schristos Currently this example only works on OSX and Windows. 294*5f2f4271Schristos Refer to the `notes of uv_fs_event_start`_ function. 295*5f2f4271Schristos 296*5f2f4271Schristos.. _notes of uv_fs_event_start: https://docs.libuv.org/en/v1.x/fs_event.html#c.uv_fs_event_start 297*5f2f4271Schristos 2980e552da7SchristosThe file change notification is started using ``uv_fs_event_init()``: 2990e552da7Schristos 3000e552da7Schristos.. rubric:: onchange/main.c - The setup 3010e552da7Schristos.. literalinclude:: ../../code/onchange/main.c 302*5f2f4271Schristos :language: c 3030e552da7Schristos :linenos: 3040e552da7Schristos :lines: 26- 3050e552da7Schristos :emphasize-lines: 15 3060e552da7Schristos 3070e552da7SchristosThe third argument is the actual file or directory to monitor. The last 3080e552da7Schristosargument, ``flags``, can be: 3090e552da7Schristos 3100e552da7Schristos.. code-block:: c 3110e552da7Schristos 3120e552da7Schristos /* 3130e552da7Schristos * Flags to be passed to uv_fs_event_start(). 3140e552da7Schristos */ 3150e552da7Schristos enum uv_fs_event_flags { 3160e552da7Schristos UV_FS_EVENT_WATCH_ENTRY = 1, 3170e552da7Schristos UV_FS_EVENT_STAT = 2, 3180e552da7Schristos UV_FS_EVENT_RECURSIVE = 4 3190e552da7Schristos }; 3200e552da7Schristos 3210e552da7Schristos``UV_FS_EVENT_WATCH_ENTRY`` and ``UV_FS_EVENT_STAT`` don't do anything (yet). 3220e552da7Schristos``UV_FS_EVENT_RECURSIVE`` will start watching subdirectories as well on 3230e552da7Schristossupported platforms. 3240e552da7Schristos 3250e552da7SchristosThe callback will receive the following arguments: 3260e552da7Schristos 3270e552da7Schristos #. ``uv_fs_event_t *handle`` - The handle. The ``path`` field of the handle 3280e552da7Schristos is the file on which the watch was set. 3290e552da7Schristos #. ``const char *filename`` - If a directory is being monitored, this is the 3300e552da7Schristos file which was changed. Only non-``null`` on Linux and Windows. May be ``null`` 3310e552da7Schristos even on those platforms. 332*5f2f4271Schristos #. ``int events`` - one of ``UV_RENAME`` or ``UV_CHANGE``, or a bitwise OR of 3330e552da7Schristos both. 334*5f2f4271Schristos #. ``int status`` - If ``status < 0``, there is an :ref:`libuv error<libuv-error-handling>`. 3350e552da7Schristos 3360e552da7SchristosIn our example we simply print the arguments and run the command using 3370e552da7Schristos``system()``. 3380e552da7Schristos 3390e552da7Schristos.. rubric:: onchange/main.c - file change notification callback 3400e552da7Schristos.. literalinclude:: ../../code/onchange/main.c 341*5f2f4271Schristos :language: c 3420e552da7Schristos :linenos: 3430e552da7Schristos :lines: 9-24 3440e552da7Schristos 3450e552da7Schristos---- 3460e552da7Schristos 3470e552da7Schristos.. [#fsnotify] inotify on Linux, FSEvents on Darwin, kqueue on BSDs, 3480e552da7Schristos ReadDirectoryChangesW on Windows, event ports on Solaris, unsupported on Cygwin 3490e552da7Schristos.. [#] see :ref:`pipes` 350