zdir - Man Page
Class for work with file-system directories
Synopsis
// This is a stable class, and may not change except for emergencies. It // is provided in stable builds. // Create a new directory item that loads in the full tree of the specified // path, optionally located under some parent path. If parent is "-", then // loads only the top-level directory, and does not use parent as a path. CZMQ_EXPORT zdir_t * zdir_new (const char *path, const char *parent); // Destroy a directory tree and all children it contains. CZMQ_EXPORT void zdir_destroy (zdir_t **self_p); // Return directory path CZMQ_EXPORT const char * zdir_path (zdir_t *self); // Return last modification time for directory. CZMQ_EXPORT time_t zdir_modified (zdir_t *self); // Return total hierarchy size, in bytes of data contained in all files // in the directory tree. CZMQ_EXPORT off_t zdir_cursize (zdir_t *self); // Return directory count CZMQ_EXPORT size_t zdir_count (zdir_t *self); // Returns a sorted list of zfile objects; Each entry in the list is a pointer // to a zfile_t item already allocated in the zdir tree. Do not destroy the // original zdir tree until you are done with this list. // Caller owns return value and must destroy it when done. CZMQ_EXPORT zlist_t * zdir_list (zdir_t *self); // Remove directory, optionally including all files that it contains, at // all levels. If force is false, will only remove the directory if empty. // If force is true, will remove all files and all subdirectories. CZMQ_EXPORT void zdir_remove (zdir_t *self, bool force); // Calculate differences between two versions of a directory tree. // Returns a list of zdir_patch_t patches. Either older or newer may // be null, indicating the directory is empty/absent. If alias is set, // generates virtual filename (minus path, plus alias). // Caller owns return value and must destroy it when done. CZMQ_EXPORT zlist_t * zdir_diff (zdir_t *older, zdir_t *newer, const char *alias); // Return full contents of directory as a zdir_patch list. // Caller owns return value and must destroy it when done. CZMQ_EXPORT zlist_t * zdir_resync (zdir_t *self, const char *alias); // Load directory cache; returns a hash table containing the SHA-1 digests // of every file in the tree. The cache is saved between runs in .cache. // Caller owns return value and must destroy it when done. CZMQ_EXPORT zhash_t * zdir_cache (zdir_t *self); // Print contents of directory to open stream CZMQ_EXPORT void zdir_fprint (zdir_t *self, FILE *file, int indent); // Print contents of directory to stdout CZMQ_EXPORT void zdir_print (zdir_t *self, int indent); // Create a new zdir_watch actor instance: // // zactor_t *watch = zactor_new (zdir_watch, NULL); // // Destroy zdir_watch instance: // // zactor_destroy (&watch); // // Enable verbose logging of commands and activity: // // zstr_send (watch, "VERBOSE"); // // Subscribe to changes to a directory path: // // zsock_send (watch, "ss", "SUBSCRIBE", "directory_path"); // // Unsubscribe from changes to a directory path: // // zsock_send (watch, "ss", "UNSUBSCRIBE", "directory_path"); // // Receive directory changes: // zsock_recv (watch, "sp", &path, &patches); // // // Delete the received data. // free (path); // zlist_destroy (&patches); CZMQ_EXPORT void zdir_watch (zsock_t *pipe, void *unused); // Self test of this class. CZMQ_EXPORT void zdir_test (bool verbose); Please add '@interface' section in './../src/zdir.c'.
Description
The zdir class gives access to the file system index. It will load a directory tree (a directory plus all child directories) into a zdir structure and then let you navigate that structure. It exists mainly to wrap non-portable OS functions to do this.
Please add @discuss section in ./../src/zdir.c.
Example
From zdir_test method.
const char *SELFTEST_DIR_RW = "src/selftest-rw"; const char *testbasedir = "zdir-test-dir"; const char *testfile1 = "initial_file"; const char *testfile2 = "test_abc"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *filepath1 = NULL; // pathname to testfile in a test, in dirpath char *filepath2 = NULL; // pathname to testfile in a test, in dirpath basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); filepath1 = zsys_sprintf ("%s/%s", basedirpath, testfile1); assert (filepath1); filepath2 = zsys_sprintf ("%s/%s", basedirpath, testfile2); assert (filepath2); /* char *relfilepath2 = NULL; // pathname to testfile in a test, in dirpath relfilepath2 = zsys_sprintf ("%s/%s", testbasedir, testfile2); assert (relfilepath2); */ // Make sure old aborted tests do not hinder us zdir_t *dir = zdir_new (basedirpath, NULL); if (dir) { zdir_remove (dir, true); zdir_destroy (&dir); } zsys_file_delete (filepath1); zsys_file_delete (filepath2); zsys_dir_delete (basedirpath); dir = zdir_new ("does-not-exist", NULL); if (dir) { zdir_remove (dir, true); zdir_destroy (&dir); } // need to create a file in the test directory we're watching // in order to ensure the directory exists zfile_t *initfile = zfile_new (basedirpath, testfile1); assert (initfile); zfile_output (initfile); fprintf (zfile_handle (initfile), "initial file\n"); zfile_close (initfile); zfile_destroy (&initfile); zdir_t *older = zdir_new (basedirpath, NULL); assert (older); if (verbose) { printf ("\n"); zdir_dump (older, 0); } zdir_t *newer = zdir_new (SELFTEST_DIR_RW, NULL); assert (newer); zlist_t *patches = zdir_diff (older, newer, "/"); assert (patches); while (zlist_size (patches)) { zdir_patch_t *patch = (zdir_patch_t *) zlist_pop (patches); zdir_patch_destroy (&patch); } zlist_destroy (&patches); zdir_destroy (&older); zdir_destroy (&newer); zdir_t *nosuch = zdir_new ("does-not-exist", NULL); assert (nosuch == NULL); // zdir_watch test: zactor_t *watch = zactor_new (zdir_watch, NULL); assert (watch); int synced; if (verbose) { zsock_send (watch, "s", "VERBOSE"); synced = zsock_wait(watch); assert ( synced == 0); } // wait for initial file to become 'stable' #ifdef CZMQ_BUILD_DRAFT_API zclock_sleep ((int)zsys_file_stable_age_msec() + 50); #else zclock_sleep (5050); #endif zsock_send (watch, "si", "TIMEOUT", 100); synced = zsock_wait(watch); assert (synced == 0); zsock_send (watch, "ss", "SUBSCRIBE", basedirpath); synced = zsock_wait(watch); assert(synced == 0); zsock_send (watch, "ss", "UNSUBSCRIBE", basedirpath); synced = zsock_wait(watch); assert(synced == 0); zsock_send (watch, "ss", "SUBSCRIBE", basedirpath); synced = zsock_wait(watch); assert(synced == 0); zfile_t *newfile = zfile_new (basedirpath, testfile2); zfile_output (newfile); fprintf (zfile_handle (newfile), "test file\n"); zfile_close (newfile); zpoller_t *watch_poll = zpoller_new (watch, NULL); // poll for a certain timeout before giving up and failing the test void* polled = NULL; #ifdef CZMQ_BUILD_DRAFT_API polled = zpoller_wait(watch_poll, (int)zsys_file_stable_age_msec() + 150); #else polled = zpoller_wait(watch_poll, 5150); #endif assert (polled == watch); // wait for notification of the file being added char *path; int rc = zsock_recv (watch, "sp", &path, &patches); assert (rc == 0); assert (streq (path, basedirpath)); freen (path); if (verbose) zsys_debug("zdir_test() : added : zlist_size (patches)=%d", zlist_size (patches) ); assert (zlist_size (patches) == 1); zdir_patch_t *patch = (zdir_patch_t *) zlist_pop (patches); if (verbose) zsys_debug("zdir_test() : added : zdir_patch_path (patch)='%s'", zdir_patch_path (patch) ); assert (streq (zdir_patch_path (patch), basedirpath)); zfile_t *patch_file = zdir_patch_file (patch); if (verbose) zsys_debug("zdir_test() : added : zfile_filename (patch_file, \"\")='%s'", zfile_filename (patch_file, "") ); assert (streq (zfile_filename (patch_file, ""), filepath2)); zdir_patch_destroy (&patch); zlist_destroy (&patches); // remove the file zfile_remove (newfile); zfile_destroy (&newfile); // poll for a certain timeout before giving up and failing the test. #ifdef CZMQ_BUILD_DRAFT_API polled = zpoller_wait(watch_poll, (int)zsys_file_stable_age_msec() + 150); #else polled = zpoller_wait(watch_poll, 5150); #endif assert (polled == watch); // wait for notification of the file being removed rc = zsock_recv (watch, "sp", &path, &patches); assert (rc == 0); assert (streq (path, basedirpath)); freen (path); if (verbose) zsys_debug("zdir_test() : removed : zlist_size (patches)=%d", zlist_size (patches) ); assert (zlist_size (patches) == 1); patch = (zdir_patch_t *) zlist_pop (patches); if (verbose) zsys_debug("zdir_test() : removed : zdir_patch_path (patch)='%s'", zdir_patch_path (patch) ); assert (streq (zdir_patch_path (patch), basedirpath)); patch_file = zdir_patch_file (patch); if (verbose) zsys_debug("zdir_test() : removed : zfile_filename (patch_file, \"\")='%s'", zfile_filename (patch_file, "") ); assert (streq (zfile_filename (patch_file, ""), filepath2)); zdir_patch_destroy (&patch); zlist_destroy (&patches); zpoller_destroy (&watch_poll); zactor_destroy (&watch); // clean up by removing the test directory. dir = zdir_new (basedirpath, NULL); assert (dir); zdir_remove (dir, true); zdir_destroy (&dir); zstr_free (&basedirpath); zstr_free (&filepath1); zstr_free (&filepath2); #if defined (__WINDOWS__) zsys_shutdown(); #endif
Authors
The czmq manual was written by the authors in the AUTHORS file.
Resources
Main web site:
Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
Copyright
Copyright (c) the Contributors as noted in the Authors file. This file is part of CZMQ, the high-level C binding for 0MQ: http://czmq.zeromq.org. This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0. If a copy of the MPL was not distributed with this file, You can obtain one at http://mozilla.org/MPL/2.0/. LICENSE included with the czmq distribution.
Notes
- 1.
zeromq-dev@lists.zeromq.org
mailto:zeromq-dev@lists.zeromq.org