xref: /netbsd-src/external/mit/libuv/dist/docs/src/guide/filesystem.rst (revision 5f2f42719cd62ff11fd913b40b7ce19f07c4fd25)
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