int zfile_test (bool verbose) { printf (" * zfile: "); // @selftest zfile_t *file = zfile_new (".", "bilbo"); assert (streq (zfile_filename (file, "."), "bilbo")); assert (zfile_is_readable (file) == false); zfile_destroy (&file); // Create a test file in some random subdirectory file = zfile_new ("./this/is/a/test", "bilbo"); int rc = zfile_output (file); assert (rc == 0); zchunk_t *chunk = zchunk_new (NULL, 100); zchunk_fill (chunk, 0, 100); // Write 100 bytes at position 1,000,000 in the file rc = zfile_write (file, chunk, 1000000); assert (rc == 0); zfile_close (file); assert (zfile_is_readable (file)); assert (zfile_cursize (file) == 1000100); assert (!zfile_is_stable (file)); zchunk_destroy (&chunk); zclock_sleep (1001); assert (zfile_is_stable (file)); // Check we can read from file rc = zfile_input (file); assert (rc == 0); chunk = zfile_read (file, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 1000100); zchunk_destroy (&chunk); // Remove file and directory zdir_t *dir = zdir_new ("./this", NULL); assert (zdir_cursize (dir) == 1000100); zdir_remove (dir, true); assert (zdir_cursize (dir) == 0); zdir_destroy (&dir); // Check we can no longer read from file assert (!zfile_is_readable (file)); rc = zfile_input (file); assert (rc == -1); zfile_destroy (&file); // @end printf ("OK\n"); return 0; }
int hydra_post_set_file (hydra_post_t *self, const char *location) { assert (self); free (self->location); int rc = 0; self->location = strdup (location); zchunk_destroy (&self->content); zfile_t *file = zfile_new (NULL, self->location); if (file && zfile_is_readable (file)) { self->content_size = zfile_cursize (file); strcpy (self->digest, zfile_digest (file)); } else rc = -1; zfile_destroy (&file); return rc; }
zconfig_t * zconfig_load (const char *filename) { // Load entire file into memory as a chunk, then process it zconfig_t *self = NULL; zfile_t *file = zfile_new (NULL, filename); if (!file) return NULL; if (zfile_input (file) == 0) { zchunk_t *chunk = zfile_read (file, zfile_cursize (file), 0); if (chunk) { self = zconfig_chunk_load (chunk); zchunk_destroy (&chunk); if (self) self->file = file; zfile_close (file); file = NULL; // Config tree now owns file handle } } zfile_destroy (&file); return self; }
JNIEXPORT jlong JNICALL Java_org_zeromq_czmq_Zfile__1_1cursize (JNIEnv *env, jclass c, jlong self) { jlong cursize_ = (jlong) zfile_cursize ((zfile_t *) (intptr_t) self); return cursize_; }
void zfile_test (bool verbose) { printf (" * zfile: "); // @selftest zfile_t *file = zfile_new (NULL, "bilbo"); assert (streq (zfile_filename (file, "."), "bilbo")); assert (zfile_is_readable (file) == false); zfile_destroy (&file); // Create a test file in some random subdirectory file = zfile_new ("./this/is/a/test", "bilbo"); int rc = zfile_output (file); assert (rc == 0); zchunk_t *chunk = zchunk_new (NULL, 100); zchunk_fill (chunk, 0, 100); // Write 100 bytes at position 1,000,000 in the file rc = zfile_write (file, chunk, 1000000); assert (rc == 0); zchunk_destroy (&chunk); zfile_close (file); assert (zfile_is_readable (file)); assert (zfile_cursize (file) == 1000100); assert (!zfile_is_stable (file)); // Now append one byte to file from outside int handle = open ("./this/is/a/test/bilbo", O_WRONLY | O_TRUNC | O_BINARY, 0); assert (handle >= 0); rc = write (handle, "Hello, World\n", 13); assert (rc == 13); close (handle); assert (zfile_has_changed (file)); zclock_sleep (1001); assert (zfile_has_changed (file)); assert (!zfile_is_stable (file)); zfile_restat (file); assert (zfile_is_stable (file)); assert (streq (zfile_digest (file), "4AB299C8AD6ED14F31923DD94F8B5F5CB89DFB54")); // Check we can read from file rc = zfile_input (file); assert (rc == 0); chunk = zfile_read (file, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_close (file); // Try some fun with symbolic links zfile_t *link = zfile_new ("./this/is/a/test", "bilbo.ln"); rc = zfile_output (link); assert (rc == 0); fprintf (zfile_handle (link), "./this/is/a/test/bilbo\n"); zfile_destroy (&link); link = zfile_new ("./this/is/a/test", "bilbo.ln"); rc = zfile_input (link); assert (rc == 0); chunk = zfile_read (link, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_destroy (&link); // Remove file and directory zdir_t *dir = zdir_new ("./this", NULL); assert (zdir_cursize (dir) == 26); zdir_remove (dir, true); assert (zdir_cursize (dir) == 0); zdir_destroy (&dir); // Check we can no longer read from file assert (zfile_is_readable (file)); zfile_restat (file); assert (!zfile_is_readable (file)); rc = zfile_input (file); assert (rc == -1); zfile_destroy (&file); // @end printf ("OK\n"); }
/// // Return the last-known size of the file. If you want this to reflect the // current situation, call zfile_restat before checking this property. off_t QZfile::cursize () { off_t rv = zfile_cursize (self); return rv; }
void zfile_test (bool verbose) { printf (" * zfile: "); // @selftest const char *SELFTEST_DIR_RW = "src/selftest-rw"; const char *testbasedir = "this"; const char *testsubdir = "is/a/test"; const char *testfile = "bilbo"; const char *testlink = "bilbo.ln"; char *basedirpath = NULL; // subdir in a test, under SELFTEST_DIR_RW char *dirpath = NULL; // subdir in a test, under basedirpath char *filepath = NULL; // pathname to testfile in a test, in dirpath char *linkpath = NULL; // pathname to testlink in a test, in dirpath basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir); assert (basedirpath); dirpath = zsys_sprintf ("%s/%s", basedirpath, testsubdir); assert (dirpath); filepath = zsys_sprintf ("%s/%s", dirpath, testfile); assert (filepath); linkpath = zsys_sprintf ("%s/%s", dirpath, testlink); assert (linkpath); // This subtest is specifically for NULL as current directory, so // no SELFTEST_DIR_RW here; testfile should have no slashes inside. // Normally tests clean up in zfile_destroy(), but if a selftest run // dies e.g. on assert(), workspace remains dirty. Better clean it up. if (zfile_exists (testfile) ) { if (verbose) zsys_debug ("zfile_test() has to remove ./%s that should not have been here", testfile); zfile_delete (testfile); } zfile_t *file = zfile_new (NULL, testfile); assert (file); assert (streq (zfile_filename (file, "."), testfile)); assert (zfile_is_readable (file) == false); zfile_destroy (&file); // Create a test file in some random subdirectory if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Creating new zfile %s", zclock_time(), filepath ); if (zfile_exists (filepath) ) { if (verbose) zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath); zfile_delete (filepath); } file = zfile_new (dirpath, testfile); assert (file); int rc = zfile_output (file); assert (rc == 0); zchunk_t *chunk = zchunk_new (NULL, 100); assert (chunk); zchunk_fill (chunk, 0, 100); // Write 100 bytes at position 1,000,000 in the file if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Writing 100 bytes at position 1,000,000 in the file", zclock_time() ); rc = zfile_write (file, chunk, 1000000); if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Wrote 100 bytes at position 1,000,000 in the file, result code %d", zclock_time(), rc ); assert (rc == 0); zchunk_destroy (&chunk); zfile_close (file); assert (zfile_is_readable (file)); assert (zfile_cursize (file) == 1000100); if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Testing if file is NOT stable (is younger than 1 sec)", zclock_time() ); assert (!zfile_is_stable (file)); if (verbose) zsys_debug ("zfile_test() at timestamp %" PRIi64 ": " "Passed the lag-dependent tests", zclock_time() ); assert (zfile_digest (file)); // Now truncate file from outside int handle = open (filepath, O_WRONLY | O_TRUNC | O_BINARY, 0); assert (handle >= 0); rc = write (handle, "Hello, World\n", 13); assert (rc == 13); close (handle); assert (zfile_has_changed (file)); #ifdef CZMQ_BUILD_DRAFT_API zclock_sleep ((int)zsys_file_stable_age_msec() + 50); #else zclock_sleep (5050); #endif assert (zfile_has_changed (file)); assert (!zfile_is_stable (file)); zfile_restat (file); assert (zfile_is_stable (file)); assert (streq (zfile_digest (file), "4AB299C8AD6ED14F31923DD94F8B5F5CB89DFB54")); // Check we can read from file rc = zfile_input (file); assert (rc == 0); chunk = zfile_read (file, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_close (file); // Check we can read lines from file rc = zfile_input (file); assert (rc == 0); const char *line = zfile_readln (file); assert (streq (line, "Hello, World")); line = zfile_readln (file); assert (line == NULL); zfile_close (file); // Try some fun with symbolic links zfile_t *link = zfile_new (dirpath, testlink); assert (link); rc = zfile_output (link); assert (rc == 0); fprintf (zfile_handle (link), "%s\n", filepath); zfile_destroy (&link); link = zfile_new (dirpath, testlink); assert (link); rc = zfile_input (link); assert (rc == 0); chunk = zfile_read (link, 1000100, 0); assert (chunk); assert (zchunk_size (chunk) == 13); zchunk_destroy (&chunk); zfile_destroy (&link); // Remove file and directory zdir_t *dir = zdir_new (basedirpath, NULL); assert (dir); assert (zdir_cursize (dir) == 26); zdir_remove (dir, true); assert (zdir_cursize (dir) == 0); zdir_destroy (&dir); // Check we can no longer read from file assert (zfile_is_readable (file)); zfile_restat (file); assert (!zfile_is_readable (file)); rc = zfile_input (file); assert (rc == -1); zfile_destroy (&file); // This set of tests is done, free the strings for reuse zstr_free (&basedirpath); zstr_free (&dirpath); zstr_free (&filepath); zstr_free (&linkpath); const char *eof_checkfile = "eof_checkfile"; filepath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, eof_checkfile); assert (filepath); if (zfile_exists (filepath) ) { if (verbose) zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath); zfile_delete (filepath); } zstr_free (&filepath); file = zfile_new (SELFTEST_DIR_RW, eof_checkfile); assert (file); // 1. Write something first rc = zfile_output (file); assert (rc == 0); chunk = zchunk_new ("123456789", 9); assert (chunk); rc = zfile_write (file, chunk, 0); assert (rc == 0); zchunk_destroy (&chunk); zfile_close (file); assert (zfile_cursize (file) == 9); // 2. Read the written something rc = zfile_input (file); assert (rc != -1); // try to read more bytes than there is in the file chunk = zfile_read (file, 1000, 0); assert (zfile_eof(file)); assert (zchunk_streq (chunk, "123456789")); zchunk_destroy (&chunk); // reading is ok chunk = zfile_read (file, 5, 0); assert (!zfile_eof(file)); assert (zchunk_streq (chunk, "12345")); zchunk_destroy (&chunk); // read from non zero offset until the end chunk = zfile_read (file, 5, 5); assert (zfile_eof(file)); assert (zchunk_streq (chunk, "6789")); zchunk_destroy (&chunk); zfile_remove (file); zfile_close (file); zfile_destroy (&file); #ifdef CZMQ_BUILD_DRAFT_API zfile_t *tempfile = zfile_tmp (); assert (tempfile); assert (zfile_filename (tempfile, NULL)); assert (zsys_file_exists (zfile_filename (tempfile, NULL))); zchunk_t *tchunk = zchunk_new ("HELLO", 6); assert (zfile_write (tempfile, tchunk, 0) == 0); zchunk_destroy (&tchunk); char *filename = strdup (zfile_filename (tempfile, NULL)); zfile_destroy (&tempfile); assert (!zsys_file_exists (filename)); zstr_free (&filename); #endif // CZMQ_BUILD_DRAFT_API #if defined (__WINDOWS__) zsys_shutdown(); #endif // @end printf ("OK\n"); }
module_t *module_add (modhash_t *mh, const char *path) { module_t *p; void *dso; const char **mod_namep; mod_main_f *mod_main; zfile_t *zf; int rc; dlerror (); if (!(dso = dlopen (path, RTLD_NOW | RTLD_LOCAL))) { msg ("%s", dlerror ()); errno = ENOENT; return NULL; } mod_main = dlsym (dso, "mod_main"); mod_namep = dlsym (dso, "mod_name"); if (!mod_main || !mod_namep || !*mod_namep) { dlclose (dso); errno = ENOENT; return NULL; } p = xzmalloc (sizeof (*p)); p->name = xstrdup (*mod_namep); p->magic = MODULE_MAGIC; p->main = mod_main; p->dso = dso; zf = zfile_new (NULL, path); p->digest = xstrdup (zfile_digest (zf)); p->size = (int)zfile_cursize (zf); zfile_destroy (&zf); if (!(p->uuid = zuuid_new ())) oom (); if (!(p->rmmod = zlist_new ())) oom (); if (!(p->subs = zlist_new ())) oom (); p->rank = mh->rank; p->zctx = mh->zctx; p->broker_h = mh->broker_h; p->heartbeat = mh->heartbeat; /* Broker end of PAIR socket is opened here. */ if (!(p->sock = zsocket_new (p->zctx, ZMQ_PAIR))) err_exit ("zsocket_new"); zsocket_set_hwm (p->sock, 0); if (zsocket_bind (p->sock, "inproc://%s", module_get_uuid (p)) < 0) err_exit ("zsock_bind inproc://%s", module_get_uuid (p)); if (!(p->broker_w = flux_zmq_watcher_create (flux_get_reactor (p->broker_h), p->sock, FLUX_POLLIN, module_cb, p))) err_exit ("flux_zmq_watcher_create"); /* Update the modhash. */ rc = zhash_insert (mh->zh_byuuid, module_get_uuid (p), p); assert (rc == 0); /* uuids are by definition unique */ zhash_freefn (mh->zh_byuuid, module_get_uuid (p), (zhash_free_fn *)module_destroy); return p; }
/// // Return the last-known size of the file. If you want this to reflect the // current situation, call zfile_restat before checking this property. off_t QmlZfile::cursize () { return zfile_cursize (self); };
zlist_t * zdir_diff (zdir_t *older, zdir_t *newer, const char *alias) { zlist_t *patches = zlist_new (); if (!patches) return NULL; zfile_t **old_files = zdir_flatten (older); zfile_t **new_files = zdir_flatten (newer); int old_index = 0; int new_index = 0; // Note that both lists are sorted, so detecting differences // is rather trivial while (old_files [old_index] || new_files [new_index]) { zfile_t *old_file = old_files [old_index]; zfile_t *new_file = new_files [new_index]; int cmp; if (!old_file) cmp = 1; // Old file was deleted at end of list else if (!new_file) cmp = -1; // New file was added at end of list else cmp = strcmp (zfile_filename (old_file, NULL), zfile_filename (new_file, NULL)); if (cmp > 0) { // New file was created if (zfile_is_stable (new_file)) { int rc = zlist_append (patches, zdir_patch_new (newer->path, new_file, patch_create, alias)); if (rc != 0) { zlist_destroy (&patches); break; } } old_index--; } else if (cmp < 0) { // Old file was deleted if (zfile_is_stable (old_file)) { int rc = zlist_append (patches, zdir_patch_new (older->path, old_file, patch_delete, alias)); if (rc != 0) { zlist_destroy (&patches); break; } } new_index--; } else if (cmp == 0 && zfile_is_stable (new_file)) { if (zfile_is_stable (old_file)) { // Old file was modified or replaced // Since we don't check file contents, treat as created // Could better do SHA check on file here if (zfile_modified (new_file) != zfile_modified (old_file) || zfile_cursize (new_file) != zfile_cursize (old_file)) { int rc = zlist_append (patches, zdir_patch_new (newer->path, new_file, patch_create, alias)); if (rc != 0) { zlist_destroy (&patches); break; } } } else { // File was created over some period of time int rc = zlist_append (patches, zdir_patch_new (newer->path, new_file, patch_create, alias)); if (rc != 0) { zlist_destroy (&patches); break; } } } old_index++; new_index++; } freen (old_files); freen (new_files); return patches; }
zdir_t * zdir_new (const char *path, const char *parent) { zdir_t *self = (zdir_t *) zmalloc (sizeof (zdir_t)); assert (self); if (parent) { if (streq (parent, "-")) { self->trimmed = true; self->path = strdup (path); if (!self->path) { zdir_destroy (&self); return NULL; } } else { self->path = (char *) zmalloc (strlen (path) + strlen (parent) + 2); if (self->path) sprintf (self->path, "%s/%s", parent, path); else { zdir_destroy (&self); return NULL; } } } else { self->path = strdup (path); if (!self->path) { zdir_destroy (&self); return NULL; } } if (self->path) self->files = zlist_new (); if (self->files) self->subdirs = zlist_new (); if (!self->subdirs) { zdir_destroy (&self); return NULL; } #if (defined (WIN32)) // On Windows, replace backslashes by normal slashes char *path_clean_ptr = self->path; while (*path_clean_ptr) { if (*path_clean_ptr == '\\') *path_clean_ptr = '/'; path_clean_ptr++; } // Remove any trailing slash if (self->path [strlen (self->path) - 1] == '/') self->path [strlen (self->path) - 1] = 0; // Win32 wants a wildcard at the end of the path char *wildcard = (char *) zmalloc (strlen (self->path) + 3); if (!wildcard) { zdir_destroy (&self); return NULL; } sprintf (wildcard, "%s/*", self->path); WIN32_FIND_DATAA entry; HANDLE handle = FindFirstFileA (wildcard, &entry); freen (wildcard); if (handle != INVALID_HANDLE_VALUE) { // We have read an entry, so return those values s_win32_populate_entry (self, &entry); while (FindNextFileA (handle, &entry)) s_win32_populate_entry (self, &entry); FindClose (handle); } #else // Remove any trailing slash if (self->path [strlen (self->path) - 1] == '/') self->path [strlen (self->path) - 1] = 0; DIR *handle = opendir (self->path); if (handle) { // readdir_r is deprecated in glibc 2.24, but readdir is still not // guaranteed to be thread safe if the same directory is accessed // by different threads at the same time. Unfortunately given it was // not a constraint before we cannot change it now as it would be an // API breakage. Use a global lock when scanning the directory to // work around it. pthread_mutex_lock (&s_readdir_mutex); struct dirent *entry = readdir (handle); pthread_mutex_unlock (&s_readdir_mutex); while (entry != NULL) { // Beware of recursion. Lock only around readdir calls. s_posix_populate_entry (self, entry); pthread_mutex_lock (&s_readdir_mutex); entry = readdir (handle); pthread_mutex_unlock (&s_readdir_mutex); } closedir (handle); } #endif else { zdir_destroy (&self); return NULL; } // Update directory signatures zdir_t *subdir = (zdir_t *) zlist_first (self->subdirs); while (subdir) { if (self->modified < subdir->modified) self->modified = subdir->modified; self->cursize += subdir->cursize; self->count += subdir->count; subdir = (zdir_t *) zlist_next (self->subdirs); } zfile_t *file = (zfile_t *) zlist_first (self->files); while (file) { if (self->modified < zfile_modified (file)) self->modified = zfile_modified (file); self->cursize += zfile_cursize (file); self->count += 1; file = (zfile_t *) zlist_next (self->files); } return self; }