Skip site navigation (1)Skip section navigation (2)

  
 
  

home | help
ZFILE(3)			   CZMQ Manual				ZFILE(3)

NAME
     zfile  -  Class for provides methods to work with files in a portable fash-
     ion.

SYNOPSIS
     //  This is a stable class, and may not change except for emergencies. It
     //  is provided in stable builds.
     //  If file exists, populates properties. CZMQ supports portable symbolic
     //  links, which are files with the extension ".ln". A symbolic link is a
     //  text file containing one line, the filename of a target file. Reading
     //  data from the symbolic link actually reads from the target file. Path
     //  may be NULL, in which case it is not used.
     CZMQ_EXPORT zfile_t *
	 zfile_new (const char *path, const char *name);

     //  Destroy a file item
     CZMQ_EXPORT void
	 zfile_destroy (zfile_t **self_p);

     //  Duplicate a file item, returns a newly constructed item. If the file
     //  is null, or memory was exhausted, returns null.
     //  Caller owns return value and must destroy it when done.
     CZMQ_EXPORT zfile_t *
	 zfile_dup (zfile_t *self);

     //  Return file name, remove path if provided
     CZMQ_EXPORT const char *
	 zfile_filename (zfile_t *self, const char *path);

     //  Refresh file properties from disk; this is not done automatically
     //  on access methods, otherwise it is not possible to compare directory
     //  snapshots.
     CZMQ_EXPORT void
	 zfile_restat (zfile_t *self);

     //  Return when the file was last modified. If you want this to reflect the
     //  current situation, call zfile_restat before checking this property.
     CZMQ_EXPORT time_t
	 zfile_modified (zfile_t *self);

     //  Return the last-known size of the file. If you want this to reflect the
     //  current situation, call zfile_restat before checking this property.
     CZMQ_EXPORT off_t
	 zfile_cursize (zfile_t *self);

     //  Return true if the file is a directory. If you want this to reflect
     //  any external changes, call zfile_restat before checking this property.
     CZMQ_EXPORT bool
	 zfile_is_directory (zfile_t *self);

     //  Return true if the file is a regular file. If you want this to reflect
     //  any external changes, call zfile_restat before checking this property.
     CZMQ_EXPORT bool
	 zfile_is_regular (zfile_t *self);

     //  Return true if the file is readable by this process. If you want this to
     //  reflect any external changes, call zfile_restat before checking this
     //  property.
     CZMQ_EXPORT bool
	 zfile_is_readable (zfile_t *self);

     //  Return true if the file is writeable by this process. If you want this
     //  to reflect any external changes, call zfile_restat before checking this
     //  property.
     CZMQ_EXPORT bool
	 zfile_is_writeable (zfile_t *self);

     //  Check if file has stopped changing and can be safely processed.
     //  Updates the file statistics from disk at every call.
     CZMQ_EXPORT bool
	 zfile_is_stable (zfile_t *self);

     //  Return true if the file was changed on disk since the zfile_t object
     //  was created, or the last zfile_restat() call made on it.
     CZMQ_EXPORT bool
	 zfile_has_changed (zfile_t *self);

     //  Remove the file from disk
     CZMQ_EXPORT void
	 zfile_remove (zfile_t *self);

     //  Open file for reading
     //  Returns 0 if OK, -1 if not found or not accessible
     CZMQ_EXPORT int
	 zfile_input (zfile_t *self);

     //  Open file for writing, creating directory if needed
     //  File is created if necessary; chunks can be written to file at any
     //  location. Returns 0 if OK, -1 if error.
     CZMQ_EXPORT int
	 zfile_output (zfile_t *self);

     //  Read chunk from file at specified position. If this was the last chunk,
     //  sets the eof property. Returns a null chunk in case of error.
     //  Caller owns return value and must destroy it when done.
     CZMQ_EXPORT zchunk_t *
	 zfile_read (zfile_t *self, size_t bytes, off_t offset);

     //  Returns true if zfile_read() just read the last chunk in the file.
     CZMQ_EXPORT bool
	 zfile_eof (zfile_t *self);

     //  Write chunk to file at specified position
     //  Return 0 if OK, else -1
     CZMQ_EXPORT int
	 zfile_write (zfile_t *self, zchunk_t *chunk, off_t offset);

     //  Read next line of text from file. Returns a pointer to the text line,
     //  or NULL if there was nothing more to read from the file.
     CZMQ_EXPORT const char *
	 zfile_readln (zfile_t *self);

     //  Close file, if open
     CZMQ_EXPORT void
	 zfile_close (zfile_t *self);

     //  Return file handle, if opened
     CZMQ_EXPORT FILE *
	 zfile_handle (zfile_t *self);

     //  Calculate SHA1 digest for file, using zdigest class.
     CZMQ_EXPORT const char *
	 zfile_digest (zfile_t *self);

     //  Self test of this class.
     CZMQ_EXPORT void
	 zfile_test (bool verbose);

     #ifdef CZMQ_BUILD_DRAFT_API
     //  *** Draft method, for development use, may change without warning ***
     //  Create new temporary file for writing via tmpfile. File is automatically
     //  deleted on destroy
     CZMQ_EXPORT zfile_t *
	 zfile_tmp (void);

     #endif // CZMQ_BUILD_DRAFT_API
     //  These methods are deprecated, and now moved to zsys class.
     CZMQ_EXPORT bool
	 zfile_exists (const char *filename);
     CZMQ_EXPORT ssize_t
	 zfile_size   (const char *filename);
     CZMQ_EXPORT mode_t
	 zfile_mode   (const char *filename);
     CZMQ_EXPORT int
	 zfile_delete (const char *filename);
     CZMQ_EXPORT bool
	 zfile_stable (const char *filename);
     CZMQ_EXPORT int
	 zfile_mkdir  (const char *pathname);
     CZMQ_EXPORT int
	 zfile_rmdir  (const char *pathname);
     CZMQ_EXPORT void
	 zfile_mode_private (void);
     CZMQ_EXPORT void
	 zfile_mode_default (void);
     Please add '@interface' section in './../src/zfile.c'.

DESCRIPTION
     The zfile class provides methods to work with disk  files.  A  file  object
     provides  the  modified  date,  current size, and type of the file. You can
     create a file object for a filename that does not yet  exist.  To	read  or
     write  data  from the file, use the input and output methods, and then read
     and write chunks. The output method lets you both read and write chunks, at
     any offset. Finally, this class provides  portable  symbolic  links.  If  a
     filename  ends  in  ".ln",  the first line of text in the file is read, and
     used as the underlying file for read/write operations. This lets you manip-
     ulate (e.g.) copy symbolic links without copying  the  perhaps  very  large
     files they point to.

     This  class  is a new API, deprecating the old zfile class (which still ex-
     ists but is implemented in zsys now).

EXAMPLE
     From zfile_test method.

	 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

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  Li-
     cense, 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

CZMQ 4.2.1			   08/27/2026				ZFILE(3)

Want to link to this manual page? Use this URL:
<https://man.freebsd.org/cgi/man.cgi?query=zfile&sektion=3&manpath=FreeBSD+Ports+15.1.quarterly>

home | help