'\" t .\" Title: zdir .\" Author: [see the "AUTHORS" section] .\" Generator: DocBook XSL Stylesheets vsnapshot .\" Date: 01/17/2021 .\" Manual: CZMQ Manual .\" Source: CZMQ 4.2.1 .\" Language: English .\" .TH "ZDIR" "3" "01/17/2021" "CZMQ 4\&.2\&.1" "CZMQ Manual" .\" ----------------------------------------------------------------- .\" * Define some portability stuff .\" ----------------------------------------------------------------- .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .\" http://bugs.debian.org/507673 .\" http://lists.gnu.org/archive/html/groff/2009-02/msg00013.html .\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ .ie \n(.g .ds Aq \(aq .el .ds Aq ' .\" ----------------------------------------------------------------- .\" * set default formatting .\" ----------------------------------------------------------------- .\" disable hyphenation .nh .\" disable justification (adjust text to left margin only) .ad l .\" ----------------------------------------------------------------- .\" * MAIN CONTENT STARTS HERE * .\" ----------------------------------------------------------------- .SH "NAME" zdir \- Class for work with file\-system directories .SH "SYNOPSIS" .sp .nf // 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 \*(Aq@interface\*(Aq section in \*(Aq\&./\&.\&./src/zdir\&.c\*(Aq\&. .fi .SH "DESCRIPTION" .sp 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\&. .sp Please add \fI@discuss\fR section in \fI\&./\&.\&./src/zdir\&.c\fR\&. .SH "EXAMPLE" .PP \fBFrom zdir_test method\fR. .sp .if n \{\ .RS 4 .\} .nf 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\*(Aqre 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\en"); zfile_close (initfile); zfile_destroy (&initfile); zdir_t *older = zdir_new (basedirpath, NULL); assert (older); if (verbose) { printf ("\en"); 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 \*(Aqstable\*(Aq #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\en"); 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)=\*(Aq%s\*(Aq", 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, \e"\e")=\*(Aq%s\*(Aq", 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)=\*(Aq%s\*(Aq", 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, \e"\e")=\*(Aq%s\*(Aq", 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 .fi .if n \{\ .RE .\} .sp .SH "AUTHORS" .sp The czmq manual was written by the authors in the AUTHORS file\&. .SH "RESOURCES" .sp Main web site: \m[blue]\fB\%\fR\m[] .sp Report bugs to the email <\m[blue]\fBzeromq\-dev@lists\&.zeromq\&.org\fR\m[]\&\s-2\u[1]\d\s+2> .SH "COPYRIGHT" .sp 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\&. .SH "NOTES" .IP " 1." 4 zeromq-dev@lists.zeromq.org .RS 4 \%mailto:zeromq-dev@lists.zeromq.org .RE