1ZFILE(3)                          CZMQ Manual                         ZFILE(3)
2
3
4

NAME

6       zfile - Class for provides methods to work with files in a portable
7       fashion.
8

SYNOPSIS

10       //  This is a stable class, and may not change except for emergencies. It
11       //  is provided in stable builds.
12       //  If file exists, populates properties. CZMQ supports portable symbolic
13       //  links, which are files with the extension ".ln". A symbolic link is a
14       //  text file containing one line, the filename of a target file. Reading
15       //  data from the symbolic link actually reads from the target file. Path
16       //  may be NULL, in which case it is not used.
17       CZMQ_EXPORT zfile_t *
18           zfile_new (const char *path, const char *name);
19
20       //  Destroy a file item
21       CZMQ_EXPORT void
22           zfile_destroy (zfile_t **self_p);
23
24       //  Duplicate a file item, returns a newly constructed item. If the file
25       //  is null, or memory was exhausted, returns null.
26       //  Caller owns return value and must destroy it when done.
27       CZMQ_EXPORT zfile_t *
28           zfile_dup (zfile_t *self);
29
30       //  Return file name, remove path if provided
31       CZMQ_EXPORT const char *
32           zfile_filename (zfile_t *self, const char *path);
33
34       //  Refresh file properties from disk; this is not done automatically
35       //  on access methods, otherwise it is not possible to compare directory
36       //  snapshots.
37       CZMQ_EXPORT void
38           zfile_restat (zfile_t *self);
39
40       //  Return when the file was last modified. If you want this to reflect the
41       //  current situation, call zfile_restat before checking this property.
42       CZMQ_EXPORT time_t
43           zfile_modified (zfile_t *self);
44
45       //  Return the last-known size of the file. If you want this to reflect the
46       //  current situation, call zfile_restat before checking this property.
47       CZMQ_EXPORT off_t
48           zfile_cursize (zfile_t *self);
49
50       //  Return true if the file is a directory. If you want this to reflect
51       //  any external changes, call zfile_restat before checking this property.
52       CZMQ_EXPORT bool
53           zfile_is_directory (zfile_t *self);
54
55       //  Return true if the file is a regular file. If you want this to reflect
56       //  any external changes, call zfile_restat before checking this property.
57       CZMQ_EXPORT bool
58           zfile_is_regular (zfile_t *self);
59
60       //  Return true if the file is readable by this process. If you want this to
61       //  reflect any external changes, call zfile_restat before checking this
62       //  property.
63       CZMQ_EXPORT bool
64           zfile_is_readable (zfile_t *self);
65
66       //  Return true if the file is writeable by this process. If you want this
67       //  to reflect any external changes, call zfile_restat before checking this
68       //  property.
69       CZMQ_EXPORT bool
70           zfile_is_writeable (zfile_t *self);
71
72       //  Check if file has stopped changing and can be safely processed.
73       //  Updates the file statistics from disk at every call.
74       CZMQ_EXPORT bool
75           zfile_is_stable (zfile_t *self);
76
77       //  Return true if the file was changed on disk since the zfile_t object
78       //  was created, or the last zfile_restat() call made on it.
79       CZMQ_EXPORT bool
80           zfile_has_changed (zfile_t *self);
81
82       //  Remove the file from disk
83       CZMQ_EXPORT void
84           zfile_remove (zfile_t *self);
85
86       //  Open file for reading
87       //  Returns 0 if OK, -1 if not found or not accessible
88       CZMQ_EXPORT int
89           zfile_input (zfile_t *self);
90
91       //  Open file for writing, creating directory if needed
92       //  File is created if necessary; chunks can be written to file at any
93       //  location. Returns 0 if OK, -1 if error.
94       CZMQ_EXPORT int
95           zfile_output (zfile_t *self);
96
97       //  Read chunk from file at specified position. If this was the last chunk,
98       //  sets the eof property. Returns a null chunk in case of error.
99       //  Caller owns return value and must destroy it when done.
100       CZMQ_EXPORT zchunk_t *
101           zfile_read (zfile_t *self, size_t bytes, off_t offset);
102
103       //  Returns true if zfile_read() just read the last chunk in the file.
104       CZMQ_EXPORT bool
105           zfile_eof (zfile_t *self);
106
107       //  Write chunk to file at specified position
108       //  Return 0 if OK, else -1
109       CZMQ_EXPORT int
110           zfile_write (zfile_t *self, zchunk_t *chunk, off_t offset);
111
112       //  Read next line of text from file. Returns a pointer to the text line,
113       //  or NULL if there was nothing more to read from the file.
114       CZMQ_EXPORT const char *
115           zfile_readln (zfile_t *self);
116
117       //  Close file, if open
118       CZMQ_EXPORT void
119           zfile_close (zfile_t *self);
120
121       //  Return file handle, if opened
122       CZMQ_EXPORT FILE *
123           zfile_handle (zfile_t *self);
124
125       //  Calculate SHA1 digest for file, using zdigest class.
126       CZMQ_EXPORT const char *
127           zfile_digest (zfile_t *self);
128
129       //  Self test of this class.
130       CZMQ_EXPORT void
131           zfile_test (bool verbose);
132
133       #ifdef CZMQ_BUILD_DRAFT_API
134       //  *** Draft method, for development use, may change without warning ***
135       //  Create new temporary file for writing via tmpfile. File is automatically
136       //  deleted on destroy
137       CZMQ_EXPORT zfile_t *
138           zfile_tmp (void);
139
140       #endif // CZMQ_BUILD_DRAFT_API
141       //  These methods are deprecated, and now moved to zsys class.
142       CZMQ_EXPORT bool
143           zfile_exists (const char *filename);
144       CZMQ_EXPORT ssize_t
145           zfile_size   (const char *filename);
146       CZMQ_EXPORT mode_t
147           zfile_mode   (const char *filename);
148       CZMQ_EXPORT int
149           zfile_delete (const char *filename);
150       CZMQ_EXPORT bool
151           zfile_stable (const char *filename);
152       CZMQ_EXPORT int
153           zfile_mkdir  (const char *pathname);
154       CZMQ_EXPORT int
155           zfile_rmdir  (const char *pathname);
156       CZMQ_EXPORT void
157           zfile_mode_private (void);
158       CZMQ_EXPORT void
159           zfile_mode_default (void);
160       Please add '@interface' section in './../src/zfile.c'.
161

DESCRIPTION

163       The zfile class provides methods to work with disk files. A file object
164       provides the modified date, current size, and type of the file. You can
165       create a file object for a filename that does not yet exist. To read or
166       write data from the file, use the input and output methods, and then
167       read and write chunks. The output method lets you both read and write
168       chunks, at any offset. Finally, this class provides portable symbolic
169       links. If a filename ends in ".ln", the first line of text in the file
170       is read, and used as the underlying file for read/write operations.
171       This lets you manipulate (e.g.) copy symbolic links without copying the
172       perhaps very large files they point to.
173
174       This class is a new API, deprecating the old zfile class (which still
175       exists but is implemented in zsys now).
176

EXAMPLE

178       From zfile_test method.
179
180           const char *SELFTEST_DIR_RW = "src/selftest-rw";
181
182           const char *testbasedir  = "this";
183           const char *testsubdir  = "is/a/test";
184           const char *testfile = "bilbo";
185           const char *testlink = "bilbo.ln";
186           char *basedirpath = NULL;   // subdir in a test, under SELFTEST_DIR_RW
187           char *dirpath = NULL;       // subdir in a test, under basedirpath
188           char *filepath = NULL;      // pathname to testfile in a test, in dirpath
189           char *linkpath = NULL;      // pathname to testlink in a test, in dirpath
190
191           basedirpath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, testbasedir);
192           assert (basedirpath);
193           dirpath = zsys_sprintf ("%s/%s", basedirpath, testsubdir);
194           assert (dirpath);
195           filepath = zsys_sprintf ("%s/%s", dirpath, testfile);
196           assert (filepath);
197           linkpath = zsys_sprintf ("%s/%s", dirpath, testlink);
198           assert (linkpath);
199
200           // This subtest is specifically for NULL as current directory, so
201           // no SELFTEST_DIR_RW here; testfile should have no slashes inside.
202           // Normally tests clean up in zfile_destroy(), but if a selftest run
203           // dies e.g. on assert(), workspace remains dirty. Better clean it up.
204           if (zfile_exists (testfile) ) {
205               if (verbose)
206                   zsys_debug ("zfile_test() has to remove ./%s that should not have been here", testfile);
207               zfile_delete (testfile);
208           }
209           zfile_t *file = zfile_new (NULL, testfile);
210           assert (file);
211           assert (streq (zfile_filename (file, "."), testfile));
212           assert (zfile_is_readable (file) == false);
213           zfile_destroy (&file);
214
215           //  Create a test file in some random subdirectory
216           if (verbose)
217               zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
218                   "Creating new zfile %s",
219                   zclock_time(), filepath );
220
221           if (zfile_exists (filepath) ) {
222               if (verbose)
223                   zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath);
224               zfile_delete (filepath);
225           }
226
227           file = zfile_new (dirpath, testfile);
228           assert (file);
229           int rc = zfile_output (file);
230           assert (rc == 0);
231           zchunk_t *chunk = zchunk_new (NULL, 100);
232           assert (chunk);
233           zchunk_fill (chunk, 0, 100);
234
235           //  Write 100 bytes at position 1,000,000 in the file
236           if (verbose)
237               zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
238                   "Writing 100 bytes at position 1,000,000 in the file",
239                   zclock_time() );
240           rc = zfile_write (file, chunk, 1000000);
241           if (verbose)
242               zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
243                   "Wrote 100 bytes at position 1,000,000 in the file, result code %d",
244                   zclock_time(), rc );
245           assert (rc == 0);
246           zchunk_destroy (&chunk);
247           zfile_close (file);
248           assert (zfile_is_readable (file));
249           assert (zfile_cursize (file) == 1000100);
250           if (verbose)
251               zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
252                   "Testing if file is NOT stable (is younger than 1 sec)",
253                   zclock_time() );
254           assert (!zfile_is_stable (file));
255           if (verbose)
256               zsys_debug ("zfile_test() at timestamp %" PRIi64 ": "
257                   "Passed the lag-dependent tests",
258                   zclock_time() );
259           assert (zfile_digest (file));
260
261           //  Now truncate file from outside
262           int handle = open (filepath, O_WRONLY | O_TRUNC | O_BINARY, 0);
263           assert (handle >= 0);
264           rc = write (handle, "Hello, World\n", 13);
265           assert (rc == 13);
266           close (handle);
267           assert (zfile_has_changed (file));
268           #ifdef CZMQ_BUILD_DRAFT_API
269           zclock_sleep ((int)zsys_file_stable_age_msec() + 50);
270           #else
271           zclock_sleep (5050);
272           #endif
273           assert (zfile_has_changed (file));
274
275           assert (!zfile_is_stable (file));
276           zfile_restat (file);
277           assert (zfile_is_stable (file));
278           assert (streq (zfile_digest (file), "4AB299C8AD6ED14F31923DD94F8B5F5CB89DFB54"));
279
280           //  Check we can read from file
281           rc = zfile_input (file);
282           assert (rc == 0);
283           chunk = zfile_read (file, 1000100, 0);
284           assert (chunk);
285           assert (zchunk_size (chunk) == 13);
286           zchunk_destroy (&chunk);
287           zfile_close (file);
288
289           //  Check we can read lines from file
290           rc = zfile_input (file);
291           assert (rc == 0);
292           const char *line = zfile_readln (file);
293           assert (streq (line, "Hello, World"));
294           line = zfile_readln (file);
295           assert (line == NULL);
296           zfile_close (file);
297
298           //  Try some fun with symbolic links
299           zfile_t *link = zfile_new (dirpath, testlink);
300           assert (link);
301           rc = zfile_output (link);
302           assert (rc == 0);
303           fprintf (zfile_handle (link), "%s\n", filepath);
304           zfile_destroy (&link);
305
306           link = zfile_new (dirpath, testlink);
307           assert (link);
308           rc = zfile_input (link);
309           assert (rc == 0);
310           chunk = zfile_read (link, 1000100, 0);
311           assert (chunk);
312           assert (zchunk_size (chunk) == 13);
313           zchunk_destroy (&chunk);
314           zfile_destroy (&link);
315
316           //  Remove file and directory
317           zdir_t *dir = zdir_new (basedirpath, NULL);
318           assert (dir);
319           assert (zdir_cursize (dir) == 26);
320           zdir_remove (dir, true);
321           assert (zdir_cursize (dir) == 0);
322           zdir_destroy (&dir);
323
324           //  Check we can no longer read from file
325           assert (zfile_is_readable (file));
326           zfile_restat (file);
327           assert (!zfile_is_readable (file));
328           rc = zfile_input (file);
329           assert (rc == -1);
330           zfile_destroy (&file);
331
332           // This set of tests is done, free the strings for reuse
333           zstr_free (&basedirpath);
334           zstr_free (&dirpath);
335           zstr_free (&filepath);
336           zstr_free (&linkpath);
337
338           const char *eof_checkfile = "eof_checkfile";
339           filepath = zsys_sprintf ("%s/%s", SELFTEST_DIR_RW, eof_checkfile);
340           assert (filepath);
341
342           if (zfile_exists (filepath) ) {
343               if (verbose)
344                   zsys_debug ("zfile_test() has to remove %s that should not have been here", filepath);
345               zfile_delete (filepath);
346           }
347           zstr_free (&filepath);
348
349           file = zfile_new (SELFTEST_DIR_RW, eof_checkfile);
350           assert (file);
351
352           //  1. Write something first
353           rc = zfile_output (file);
354           assert (rc == 0);
355           chunk = zchunk_new ("123456789", 9);
356           assert (chunk);
357
358           rc = zfile_write (file, chunk, 0);
359           assert (rc == 0);
360           zchunk_destroy (&chunk);
361           zfile_close (file);
362           assert (zfile_cursize (file) == 9);
363
364           // 2. Read the written something
365           rc = zfile_input (file);
366           assert (rc != -1);
367           // try to read more bytes than there is in the file
368           chunk = zfile_read (file, 1000, 0);
369           assert (zfile_eof(file));
370           assert (zchunk_streq (chunk, "123456789"));
371           zchunk_destroy (&chunk);
372
373           // reading is ok
374           chunk = zfile_read (file, 5, 0);
375           assert (!zfile_eof(file));
376           assert (zchunk_streq (chunk, "12345"));
377           zchunk_destroy (&chunk);
378
379           // read from non zero offset until the end
380           chunk = zfile_read (file, 5, 5);
381           assert (zfile_eof(file));
382           assert (zchunk_streq (chunk, "6789"));
383           zchunk_destroy (&chunk);
384           zfile_remove (file);
385           zfile_close (file);
386           zfile_destroy (&file);
387
388           #ifdef CZMQ_BUILD_DRAFT_API
389           zfile_t *tempfile = zfile_tmp ();
390           assert (tempfile);
391           assert (zfile_filename (tempfile, NULL));
392           assert (zsys_file_exists (zfile_filename (tempfile, NULL)));
393           zchunk_t *tchunk = zchunk_new ("HELLO", 6);
394           assert (zfile_write (tempfile, tchunk, 0) == 0);
395           zchunk_destroy (&tchunk);
396
397           char *filename = strdup (zfile_filename (tempfile, NULL));
398           zfile_destroy (&tempfile);
399           assert (!zsys_file_exists (filename));
400           zstr_free (&filename);
401           #endif // CZMQ_BUILD_DRAFT_API
402
403           #if defined (__WINDOWS__)
404           zsys_shutdown();
405           #endif
406
407

AUTHORS

409       The czmq manual was written by the authors in the AUTHORS file.
410

RESOURCES

412       Main web site:
413
414       Report bugs to the email <zeromq-dev@lists.zeromq.org[1]>
415
417       Copyright (c) the Contributors as noted in the AUTHORS file. This file
418       is part of CZMQ, the high-level C binding for 0MQ:
419       http://czmq.zeromq.org. This Source Code Form is subject to the terms
420       of the Mozilla Public License, v. 2.0. If a copy of the MPL was not
421       distributed with this file, You can obtain one at
422       http://mozilla.org/MPL/2.0/. LICENSE included with the czmq
423       distribution.
424

NOTES

426        1. zeromq-dev@lists.zeromq.org
427           mailto:zeromq-dev@lists.zeromq.org
428
429
430
431CZMQ 4.2.1                        01/19/2023                          ZFILE(3)
Impressum