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

FreeBSD Manual Pages

  
 
  

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

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

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 manipulate	(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
       exists 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 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

CZMQ 4.2.1			  11/01/2025			      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.0>

home | help