This source file includes following definitions.
- crm_build_path
- generate_series_filename
- get_last_sequence
- write_last_sequence
- crm_chown_last_sequence
- crm_is_writable
- crm_sync_directory
- crm_read_contents
- crm_write_sync
- crm_set_nonblocking
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 #include <crm_internal.h>
20
21 #ifndef _GNU_SOURCE
22 # define _GNU_SOURCE
23 #endif
24
25 #include <sys/param.h>
26 #include <sys/types.h>
27 #include <sys/stat.h>
28
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <string.h>
32 #include <stdlib.h>
33 #include <fcntl.h>
34 #include <dirent.h>
35 #include <pwd.h>
36 #include <grp.h>
37
38 #include <crm/crm.h>
39 #include <crm/common/util.h>
40
41
42
43
44
45
46
47
48
49 void
50 crm_build_path(const char *path_c, mode_t mode)
51 {
52 int offset = 1, len = 0;
53 char *path = strdup(path_c);
54
55 CRM_CHECK(path != NULL, return);
56 for (len = strlen(path); offset < len; offset++) {
57 if (path[offset] == '/') {
58 path[offset] = 0;
59 if (mkdir(path, mode) < 0 && errno != EEXIST) {
60 crm_perror(LOG_ERR, "Could not create directory '%s'", path);
61 break;
62 }
63 path[offset] = '/';
64 }
65 }
66 if (mkdir(path, mode) < 0 && errno != EEXIST) {
67 crm_perror(LOG_ERR, "Could not create directory '%s'", path);
68 }
69
70 free(path);
71 }
72
73
74
75
76
77
78
79
80
81
82
83
84
85 char *
86 generate_series_filename(const char *directory, const char *series, int sequence, gboolean bzip)
87 {
88 int len = 40;
89 char *filename = NULL;
90 const char *ext = "raw";
91
92 CRM_CHECK(directory != NULL, return NULL);
93 CRM_CHECK(series != NULL, return NULL);
94
95 #if !HAVE_BZLIB_H
96 bzip = FALSE;
97 #endif
98
99 len += strlen(directory);
100 len += strlen(series);
101 filename = malloc(len);
102 CRM_CHECK(filename != NULL, return NULL);
103
104 if (bzip) {
105 ext = "bz2";
106 }
107 sprintf(filename, "%s/%s-%d.%s", directory, series, sequence, ext);
108
109 return filename;
110 }
111
112
113
114
115
116
117
118
119
120
121 int
122 get_last_sequence(const char *directory, const char *series)
123 {
124 FILE *file_strm = NULL;
125 int start = 0, length = 0, read_len = 0;
126 char *series_file = NULL;
127 char *buffer = NULL;
128 int seq = 0;
129 int len = 36;
130
131 CRM_CHECK(directory != NULL, return 0);
132 CRM_CHECK(series != NULL, return 0);
133
134 len += strlen(directory);
135 len += strlen(series);
136 series_file = malloc(len);
137 CRM_CHECK(series_file != NULL, return 0);
138 sprintf(series_file, "%s/%s.last", directory, series);
139
140 file_strm = fopen(series_file, "r");
141 if (file_strm == NULL) {
142 crm_debug("Series file %s does not exist", series_file);
143 free(series_file);
144 return 0;
145 }
146
147
148 start = ftell(file_strm);
149 fseek(file_strm, 0L, SEEK_END);
150 length = ftell(file_strm);
151 fseek(file_strm, 0L, start);
152
153 CRM_ASSERT(length >= 0);
154 CRM_ASSERT(start == ftell(file_strm));
155
156 if (length <= 0) {
157 crm_info("%s was not valid", series_file);
158 free(buffer);
159 buffer = NULL;
160
161 } else {
162 crm_trace("Reading %d bytes from file", length);
163 buffer = calloc(1, (length + 1));
164 read_len = fread(buffer, 1, length, file_strm);
165 if (read_len != length) {
166 crm_err("Calculated and read bytes differ: %d vs. %d", length, read_len);
167 free(buffer);
168 buffer = NULL;
169 }
170 }
171
172 seq = crm_parse_int(buffer, "0");
173 fclose(file_strm);
174
175 crm_trace("Found %d in %s", seq, series_file);
176
177 free(series_file);
178 free(buffer);
179 return seq;
180 }
181
182
183
184
185
186
187
188
189
190
191
192
193 void
194 write_last_sequence(const char *directory, const char *series, int sequence, int max)
195 {
196 int rc = 0;
197 int len = 36;
198 FILE *file_strm = NULL;
199 char *series_file = NULL;
200
201 CRM_CHECK(directory != NULL, return);
202 CRM_CHECK(series != NULL, return);
203
204 if (max == 0) {
205 return;
206 }
207 if (max > 0 && sequence >= max) {
208 sequence = 0;
209 }
210
211 len += strlen(directory);
212 len += strlen(series);
213 series_file = malloc(len);
214
215 if (series_file) {
216 sprintf(series_file, "%s/%s.last", directory, series);
217 file_strm = fopen(series_file, "w");
218 }
219
220 if (file_strm != NULL) {
221 rc = fprintf(file_strm, "%d", sequence);
222 if (rc < 0) {
223 crm_perror(LOG_ERR, "Cannot write to series file %s", series_file);
224 }
225
226 } else {
227 crm_err("Cannot open series file %s for writing", series_file);
228 }
229
230 if (file_strm != NULL) {
231 fflush(file_strm);
232 fclose(file_strm);
233 }
234
235 crm_trace("Wrote %d to %s", sequence, series_file);
236 free(series_file);
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250 int
251 crm_chown_last_sequence(const char *directory, const char *series, uid_t uid, gid_t gid)
252 {
253 char *series_file = NULL;
254 int rc;
255
256 CRM_CHECK((directory != NULL) && (series != NULL), errno = EINVAL; return -1);
257
258 series_file = crm_strdup_printf("%s/%s.last", directory, series);
259 CRM_CHECK(series_file != NULL, return -1);
260
261 rc = chown(series_file, uid, gid);
262 free(series_file);
263 return rc;
264 }
265
266
267
268
269
270
271
272
273
274
275
276
277
278 gboolean
279 crm_is_writable(const char *dir, const char *file,
280 const char *user, const char *group, gboolean need_both)
281 {
282 int s_res = -1;
283 struct stat buf;
284 char *full_file = NULL;
285 const char *target = NULL;
286
287 gboolean pass = TRUE;
288 gboolean readwritable = FALSE;
289
290 CRM_ASSERT(dir != NULL);
291 if (file != NULL) {
292 full_file = crm_concat(dir, file, '/');
293 target = full_file;
294 s_res = stat(full_file, &buf);
295 if (s_res == 0 && S_ISREG(buf.st_mode) == FALSE) {
296 crm_err("%s must be a regular file", target);
297 pass = FALSE;
298 goto out;
299 }
300 }
301
302 if (s_res != 0) {
303 target = dir;
304 s_res = stat(dir, &buf);
305 if (s_res != 0) {
306 crm_err("%s must exist and be a directory", dir);
307 pass = FALSE;
308 goto out;
309
310 } else if (S_ISDIR(buf.st_mode) == FALSE) {
311 crm_err("%s must be a directory", dir);
312 pass = FALSE;
313 }
314 }
315
316 if (user) {
317 struct passwd *sys_user = NULL;
318
319 sys_user = getpwnam(user);
320 readwritable = (sys_user != NULL
321 && buf.st_uid == sys_user->pw_uid && (buf.st_mode & (S_IRUSR | S_IWUSR)));
322 if (readwritable == FALSE) {
323 crm_err("%s must be owned and r/w by user %s", target, user);
324 if (need_both) {
325 pass = FALSE;
326 }
327 }
328 }
329
330 if (group) {
331 struct group *sys_grp = getgrnam(group);
332
333 readwritable = (sys_grp != NULL
334 && buf.st_gid == sys_grp->gr_gid && (buf.st_mode & (S_IRGRP | S_IWGRP)));
335 if (readwritable == FALSE) {
336 if (need_both || user == NULL) {
337 pass = FALSE;
338 crm_err("%s must be owned and r/w by group %s", target, group);
339 } else {
340 crm_warn("%s should be owned and r/w by group %s", target, group);
341 }
342 }
343 }
344
345 out:
346 free(full_file);
347 return pass;
348 }
349
350
351
352
353
354
355
356
357 void
358 crm_sync_directory(const char *name)
359 {
360 int fd;
361 DIR *directory;
362
363 directory = opendir(name);
364 if (directory == NULL) {
365 crm_perror(LOG_ERR, "Could not open %s for syncing", name);
366 return;
367 }
368
369 fd = dirfd(directory);
370 if (fd < 0) {
371 crm_perror(LOG_ERR, "Could not obtain file descriptor for %s", name);
372 return;
373 }
374
375 if (fsync(fd) < 0) {
376 crm_perror(LOG_ERR, "Could not sync %s", name);
377 }
378 if (closedir(directory) < 0) {
379 crm_perror(LOG_ERR, "Could not close %s after fsync", name);
380 }
381 }
382
383
384
385
386
387
388
389
390
391
392
393
394 char *
395 crm_read_contents(const char *filename)
396 {
397 char *contents = NULL;
398 FILE *fp;
399 int length, read_len;
400
401 errno = 0;
402
403 fp = fopen(filename, "r");
404 if (fp == NULL) {
405 return NULL;
406 }
407
408 fseek(fp, 0L, SEEK_END);
409 length = ftell(fp);
410
411 if (length > 0) {
412 contents = calloc(length + 1, sizeof(char));
413 if (contents == NULL) {
414 fclose(fp);
415 return NULL;
416 }
417
418 crm_trace("Reading %d bytes from %s", length, filename);
419 rewind(fp);
420 read_len = fread(contents, 1, length, fp);
421 if (read_len != length) {
422 free(contents);
423 contents = NULL;
424 }
425 }
426
427 fclose(fp);
428 return contents;
429 }
430
431
432
433
434
435
436
437
438
439
440 int
441 crm_write_sync(int fd, const char *contents)
442 {
443 int rc = 0;
444 FILE *fp = fdopen(fd, "w");
445
446 if (fp == NULL) {
447 return -1;
448 }
449 if ((contents != NULL) && (fprintf(fp, "%s", contents) < 0)) {
450 rc = -1;
451 }
452 if (fflush(fp) != 0) {
453 rc = -1;
454 }
455 if (fsync(fileno(fp)) < 0) {
456 rc = -1;
457 }
458 fclose(fp);
459 return rc;
460 }
461
462
463
464
465
466
467
468
469
470 int
471 crm_set_nonblocking(int fd)
472 {
473 int flag = fcntl(fd, F_GETFL);
474
475 if (flag < 0) {
476 return -errno;
477 }
478 if (fcntl(fd, F_SETFL, flag | O_NONBLOCK) < 0) {
479 return -errno;
480 }
481 return pcmk_ok;
482 }