1 /* =========================================================================
2 zdir_patch - work with directory patches
3 A patch is a change to the directory (create/delete).
4
5 Copyright (c) the Contributors as noted in the AUTHORS file.
6 This file is part of CZMQ, the high-level C binding for 0MQ:
7 http://czmq.zeromq.org.
8
9 This Source Code Form is subject to the terms of the Mozilla Public
10 License, v. 2.0. If a copy of the MPL was not distributed with this
11 file, You can obtain one at http://mozilla.org/MPL/2.0/.
12 =========================================================================
13 */
14
15 /*
16 @header
17 The zdir_patch class works with one patch, which says "create this
18 file" or "delete this file" (referring to a zfile item each time).
19 @discuss
20 @end
21 */
22
23 #include "czmq_classes.h"
24
25 // Structure of our class
26 // If you modify this beware to also change _dup
27
28 struct _zdir_patch_t {
29 char *path; // Directory path
30 char *vpath; // Virtual file path
31 zfile_t *file; // File we refer to
32 int op; // Operation
33 char *digest; // File SHA-1 digest
34 };
35
36
37 // --------------------------------------------------------------------------
38 // Constructor
39 // Create new patch, create virtual path from alias
40
41 zdir_patch_t *
zdir_patch_new(const char * path,zfile_t * file,int op,const char * alias)42 zdir_patch_new (const char *path, zfile_t *file, int op, const char *alias)
43 {
44 zdir_patch_t *self = (zdir_patch_t *) zmalloc (sizeof (zdir_patch_t));
45 assert (self);
46 self->path = strdup (path);
47 assert (self->path);
48 self->file = zfile_dup (file);
49 assert (self->file);
50 self->op = op;
51
52 // Calculate virtual path for patch (remove path, prefix alias)
53 const char *filename = zfile_filename (file, path);
54 assert (filename);
55 assert (*filename != '/');
56
57 self->vpath = (char *) zmalloc (strlen (alias) + strlen (filename) + 2);
58 assert (self->vpath);
59
60 if (strlen (alias) && alias [strlen (alias) - 1] == '/')
61 sprintf (self->vpath, "%s%s", alias, filename);
62 else
63 sprintf (self->vpath, "%s/%s", alias, filename);
64 return self;
65 }
66
67
68 // --------------------------------------------------------------------------
69 // Destroy a patch
70
71 void
zdir_patch_destroy(zdir_patch_t ** self_p)72 zdir_patch_destroy (zdir_patch_t **self_p)
73 {
74 assert (self_p);
75 if (*self_p) {
76 zdir_patch_t *self = *self_p;
77 freen (self->path);
78 freen (self->vpath);
79 freen (self->digest);
80 zfile_destroy (&self->file);
81 freen (self);
82 *self_p = NULL;
83 }
84 }
85
86
87 // --------------------------------------------------------------------------
88 // Create copy of a patch. If the patch is null, or memory was exhausted,
89 // returns null.
90
91 zdir_patch_t *
zdir_patch_dup(zdir_patch_t * self)92 zdir_patch_dup (zdir_patch_t *self)
93 {
94 if (self) {
95 zdir_patch_t *copy = (zdir_patch_t *) zmalloc (sizeof (zdir_patch_t));
96 if (copy) {
97 copy->op = self->op;
98 copy->path = strdup (self->path);
99 if (copy->path)
100 copy->file = zfile_dup (self->file);
101 if (copy->file)
102 copy->vpath = strdup (self->vpath);
103 if (copy->vpath)
104 // Don't recalculate hash when we duplicate patch
105 copy->digest = self->digest? strdup (self->digest): NULL;
106
107 if (copy->digest == NULL && copy->op != patch_delete)
108 zdir_patch_destroy (©);
109 }
110 return copy;
111 }
112 else
113 return NULL;
114 }
115
116
117 // --------------------------------------------------------------------------
118 // Return patch file directory path
119
120 const char *
zdir_patch_path(zdir_patch_t * self)121 zdir_patch_path (zdir_patch_t *self)
122 {
123 assert (self);
124 return self->path;
125 }
126
127
128 // --------------------------------------------------------------------------
129 // Return patch file item
130
131 zfile_t *
zdir_patch_file(zdir_patch_t * self)132 zdir_patch_file (zdir_patch_t *self)
133 {
134 assert (self);
135 return self->file;
136 }
137
138
139 // --------------------------------------------------------------------------
140 // Return operation
141
142 int
zdir_patch_op(zdir_patch_t * self)143 zdir_patch_op (zdir_patch_t *self)
144 {
145 assert (self);
146 return self->op;
147 }
148
149
150 // --------------------------------------------------------------------------
151 // Return patch virtual file path
152
153 const char *
zdir_patch_vpath(zdir_patch_t * self)154 zdir_patch_vpath (zdir_patch_t *self)
155 {
156 assert (self);
157 return self->vpath;
158 }
159
160
161 // --------------------------------------------------------------------------
162 // Calculate hash digest for file (create only)
163
164 void
zdir_patch_digest_set(zdir_patch_t * self)165 zdir_patch_digest_set (zdir_patch_t *self)
166 {
167 if (self->op == patch_create
168 && self->digest == NULL) {
169 self->digest = strdup (zfile_digest (self->file));
170 assert (self->digest);
171 }
172
173 }
174
175
176 // --------------------------------------------------------------------------
177 // Return hash digest for patch file (create only)
178
179 const char *
zdir_patch_digest(zdir_patch_t * self)180 zdir_patch_digest (zdir_patch_t *self)
181 {
182 assert (self);
183 return self->digest;
184 }
185
186
187 // --------------------------------------------------------------------------
188 // Self test of this class
189
190 void
zdir_patch_test(bool verbose)191 zdir_patch_test (bool verbose)
192 {
193 printf (" * zdir_patch: ");
194
195 // @selftest
196
197 const char *SELFTEST_DIR_RW = "src/selftest-rw";
198
199 const char *testfile = "bilbo";
200 const char *prefix = "/";
201 char *prefixed_testfile = zsys_sprintf ("%s%s", prefix, testfile);
202 assert (prefixed_testfile);
203
204 // Make sure old aborted tests do not hinder us
205 zsys_file_delete (prefixed_testfile);
206
207 zfile_t *file = zfile_new (SELFTEST_DIR_RW, testfile);
208 assert (file);
209 zdir_patch_t *patch = zdir_patch_new (SELFTEST_DIR_RW, file, patch_create, prefix);
210 assert (patch);
211 zfile_destroy (&file);
212
213 file = zdir_patch_file (patch);
214 assert (file);
215 assert (streq (zfile_filename (file, SELFTEST_DIR_RW), testfile));
216 assert (streq (zdir_patch_vpath (patch), prefixed_testfile));
217 zdir_patch_destroy (&patch);
218
219 zstr_free (&prefixed_testfile);
220
221 #if defined (__WINDOWS__)
222 zsys_shutdown();
223 #endif
224 // @end
225
226 printf ("OK\n");
227 }
228