Add.
[shishi.git] / db / fileutil.c
blob20f75e8ded5eeec977fa32a99d83fe0883e57d8a
1 /* fileutil.c --- Utility functions used by file.c.
2 * Copyright (C) 2002, 2003, 2004, 2007 Simon Josefsson
4 * This file is part of Shishi.
6 * Shishi is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License as published by
8 * the Free Software Foundation; either version 2 of the License, or
9 * (at your option) any later version.
11 * Shishi is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with Shishi; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
22 #include "info.h"
24 /* For stat. */
25 #include <sys/stat.h>
26 #include <sys/types.h>
27 #include <unistd.h>
29 /* For readdir. */
30 #include <dirent.h>
32 #include <errno.h>
33 #ifndef errno
34 extern int errno;
35 #endif
37 #include "xreadlink.h"
39 /* Get specification. */
40 #include "fileutil.h"
42 #define ishex(c) ((c >= '0' || c <= '9') || (c >= 'a' || c <= 'f'))
43 #define tohex(c1,c2) (((c1 - '0' > 9 ? c1 - 'a' + 10 : c1 - '0') << 4) | \
44 (c2 - '0' > 9 ? c2 - 'a' + 10 : c2 - '0'))
46 static char *
47 unescape_filename (const char *path)
49 char *out = strdup (path);
50 char *p = out;
52 while (*path)
54 if (path[0] == '%' &&
55 path[1] && ishex (path[1]) && path[2] && ishex (path[2]))
57 *p++ = tohex (path[1], path[2]);
58 path += 3;
60 else
61 *p++ = *path++;
63 *p = '\0';
65 return out;
68 static char *
69 escape_filename (const char *path)
71 char *out = malloc (strlen (path) * 3 + 1);
72 char *p = out;
74 while (*path)
76 if ((path[0] >= 'a' && path[0] <= 'z') ||
77 (path[0] >= 'A' && path[0] <= 'Z') ||
78 (path[0] >= '0' && path[0] <= '9') ||
79 path[0] == '-' || path[0] == '.')
80 *p++ = *path++;
81 else
83 int i;
84 *p++ = '%';
85 i = (*path & 0xF0) >> 4;
86 *p++ = i > 10 ? 'a' + i - 10 : '0' + i;
87 i = (*path & 0x0f);
88 *p++ = i > 10 ? 'a' + i - 10 : '0' + i;
89 path++;
92 *p = '\0';
94 return out;
97 int
98 _shisa_isdir (const char *path)
100 struct stat buf;
101 int rc;
103 rc = stat (path, &buf);
104 if (rc != 0 || !S_ISDIR (buf.st_mode))
105 return 0;
107 return 1;
110 static int
111 isdir2 (const char *path1, const char *path2)
113 char *tmp;
114 int rc;
116 asprintf (&tmp, "%s/%s", path1, path2);
118 rc = _shisa_isdir (tmp);
120 free (tmp);
122 return rc;
127 _shisa_isdir2 (const char *path1, const char *realm)
129 char *saferealm = escape_filename (realm);
130 char *tmp;
131 int rc;
133 asprintf (&tmp, "%s/%s", path1, saferealm);
134 free (saferealm);
136 rc = _shisa_isdir (tmp);
138 free (tmp);
140 return rc;
144 _shisa_isdir3 (const char *path1, const char *realm, const char *principal)
146 char *saferealm = escape_filename (realm);
147 char *safeprincipal = escape_filename (principal);
148 char *tmp;
149 int rc;
151 asprintf (&tmp, "%s/%s/%s", path1, saferealm, safeprincipal);
152 free (saferealm);
153 free (safeprincipal);
155 rc = _shisa_isdir (tmp);
157 free (tmp);
159 return rc;
163 _shisa_isdir4 (const char *path1, const char *realm,
164 const char *principal, const char *path4)
166 char *saferealm = escape_filename (realm);
167 char *safeprincipal = escape_filename (principal);
168 char *tmp;
169 int rc;
171 asprintf (&tmp, "%s/%s/%s/%s", path1, saferealm, safeprincipal, path4);
172 free (saferealm);
173 free (safeprincipal);
175 rc = _shisa_isdir (tmp);
177 free (tmp);
179 return rc;
183 _shisa_mkdir (const char *file)
185 int rc;
187 rc = mkdir (file, S_IRUSR | S_IWUSR | S_IXUSR);
188 if (rc != 0)
190 perror (file);
191 return -1;
194 return 0;
198 _shisa_mkdir2 (const char *path1, const char *realm)
200 char *saferealm = escape_filename (realm);
201 char *tmp;
202 int rc;
204 asprintf (&tmp, "%s/%s", path1, saferealm);
205 free (saferealm);
207 rc = _shisa_mkdir (tmp);
209 free (tmp);
211 return rc;
215 _shisa_mkdir3 (const char *path1, const char *realm, const char *principal)
217 char *saferealm = escape_filename (realm);
218 char *safeprincipal = escape_filename (principal);
219 char *tmp;
220 int rc;
222 asprintf (&tmp, "%s/%s/%s", path1, saferealm, safeprincipal);
223 free (saferealm);
224 free (safeprincipal);
226 rc = _shisa_mkdir (tmp);
228 free (tmp);
230 return rc;
234 _shisa_mkdir4 (const char *path1, const char *realm,
235 const char *principal, const char *path4)
237 char *saferealm = escape_filename (realm);
238 char *safeprincipal = escape_filename (principal);
239 char *tmp;
240 int rc;
242 asprintf (&tmp, "%s/%s/%s/%s", path1, saferealm, safeprincipal, path4);
243 free (saferealm);
244 free (safeprincipal);
246 rc = _shisa_mkdir (tmp);
248 free (tmp);
250 return rc;
254 _shisa_rmdir (const char *file)
256 int rc;
258 rc = rmdir (file);
259 if (rc != 0)
261 perror (file);
262 return -1;
265 return 0;
269 _shisa_rmdir2 (const char *path1, const char *realm)
271 char *saferealm = escape_filename (realm);
272 char *tmp;
273 int rc;
275 asprintf (&tmp, "%s/%s", path1, saferealm);
276 free (saferealm);
278 rc = _shisa_rmdir (tmp);
280 free (tmp);
282 return rc;
286 _shisa_rmdir3 (const char *path1, const char *realm, const char *principal)
288 char *saferealm = escape_filename (realm);
289 char *safeprincipal = escape_filename (principal);
290 char *tmp;
291 int rc;
293 asprintf (&tmp, "%s/%s/%s", path1, saferealm, safeprincipal);
294 free (saferealm);
295 free (safeprincipal);
297 rc = _shisa_rmdir (tmp);
299 free (tmp);
301 return rc;
305 _shisa_rmdir4 (const char *path1, const char *realm,
306 const char *principal, const char *path4)
308 char *saferealm = escape_filename (realm);
309 char *safeprincipal = escape_filename (principal);
310 char *tmp;
311 int rc;
313 asprintf (&tmp, "%s/%s/%s/%s", path1, saferealm, safeprincipal, path4);
314 free (saferealm);
315 free (safeprincipal);
317 rc = _shisa_rmdir (tmp);
319 free (tmp);
321 return rc;
324 static time_t
325 mtime (const char *file)
327 struct stat buf;
328 int rc;
330 rc = stat (file, &buf);
331 if (rc != 0 || !S_ISREG (buf.st_mode))
332 return (time_t) - 1;
334 return buf.st_atime;
338 _shisa_mtime4 (const char *path1,
339 const char *realm, const char *principal, const char *path4)
341 char *saferealm = escape_filename (realm);
342 char *safeprincipal = escape_filename (principal);
343 char *tmp;
344 int rc;
346 asprintf (&tmp, "%s/%s/%s/%s", path1, saferealm, safeprincipal, path4);
347 free (saferealm);
348 free (safeprincipal);
350 rc = mtime (tmp);
352 free (tmp);
354 return rc;
357 static int
358 isfile (const char *path)
360 struct stat buf;
361 int rc;
363 rc = stat (path, &buf);
364 if (rc != 0 || !S_ISREG (buf.st_mode))
365 return 0;
367 return 1;
371 _shisa_isfile4 (const char *path1,
372 const char *realm, const char *principal, const char *path4)
374 char *saferealm = escape_filename (realm);
375 char *safeprincipal = escape_filename (principal);
376 char *tmp;
377 int rc;
379 asprintf (&tmp, "%s/%s/%s/%s", path1, saferealm, safeprincipal, path4);
380 free (saferealm);
381 free (safeprincipal);
383 rc = isfile (tmp);
385 free (tmp);
387 return rc;
390 static uint32_t
391 uint32link (const char *file)
393 char *linkname;
395 linkname = xreadlink (file);
396 if (linkname == NULL)
397 return 0;
399 return atol (linkname);
403 _shisa_uint32link4 (const char *path1,
404 const char *realm,
405 const char *principal, const char *path4)
407 char *saferealm = escape_filename (realm);
408 char *safeprincipal = escape_filename (principal);
409 char *tmp;
410 int rc;
412 asprintf (&tmp, "%s/%s/%s/%s", path1, saferealm, safeprincipal, path4);
413 free (saferealm);
414 free (safeprincipal);
416 rc = uint32link (tmp);
418 free (tmp);
420 return rc;
423 static int
424 ls_1 (const char *path, int onlydir, char ***files, size_t * nfiles,
425 DIR * dir)
427 struct dirent *de;
429 while (errno = 0, (de = readdir (dir)) != NULL)
431 if (strcmp (de->d_name, ".") == 0 || strcmp (de->d_name, "..") == 0)
432 continue;
433 if (!onlydir || isdir2 (path, de->d_name))
435 if (files)
437 *files = xrealloc (*files, (*nfiles + 1) * sizeof (**files));
438 (*files)[(*nfiles)] = unescape_filename (de->d_name);
440 (*nfiles)++;
444 if (errno != 0)
446 size_t i;
448 perror (path);
450 if (files)
452 for (i = 0; i < *nfiles; i++)
453 free (**files);
454 if (*nfiles > 0)
455 free (*files);
458 return -1;
461 return 0;
464 static int
465 ls (const char *path, int onlydir, char ***files, size_t * nfiles)
467 DIR *dir;
468 int rc;
470 dir = opendir (path);
471 if (dir == NULL)
473 perror (path);
474 return -1;
477 if (ls_1 (path, onlydir, files, nfiles, dir) != 0)
479 rc = closedir (dir);
480 if (rc != 0)
481 perror (path);
482 return -1;
485 rc = closedir (dir);
486 if (rc != 0)
488 size_t i;
490 perror (path);
492 if (files)
494 for (i = 0; i < *nfiles; i++)
495 free (**files);
496 if (*nfiles > 0)
497 free (*files);
500 return -1;
503 return 0;
507 _shisa_ls (const char *path, char ***files, size_t * nfiles)
509 return ls (path, 0, files, nfiles);
513 _shisa_ls2 (const char *path, const char *realm,
514 char ***files, size_t * nfiles)
516 char *saferealm = escape_filename (realm);
517 char *tmp;
518 int rc;
520 asprintf (&tmp, "%s/%s", path, saferealm);
521 free (saferealm);
523 rc = _shisa_ls (tmp, files, nfiles);
525 free (tmp);
527 return rc;
531 _shisa_ls3 (const char *path, const char *realm,
532 const char *principal, char ***files, size_t * nfiles)
534 char *saferealm = escape_filename (realm);
535 char *safeprincipal = escape_filename (principal);
536 char *tmp;
537 int rc;
539 asprintf (&tmp, "%s/%s/%s", path, saferealm, safeprincipal);
540 free (saferealm);
541 free (safeprincipal);
543 rc = _shisa_ls (tmp, files, nfiles);
545 free (tmp);
547 return rc;
551 _shisa_ls4 (const char *path, const char *realm,
552 const char *principal, const char *path4,
553 char ***files, size_t * nfiles)
555 char *saferealm = escape_filename (realm);
556 char *safeprincipal = escape_filename (principal);
557 char *tmp;
558 int rc;
560 asprintf (&tmp, "%s/%s/%s/%s", path, saferealm, safeprincipal, path4);
561 free (saferealm);
562 free (safeprincipal);
564 rc = _shisa_ls (tmp, files, nfiles);
566 free (tmp);
568 return rc;
572 _shisa_lsdir (const char *path, char ***files, size_t * nfiles)
574 return ls (path, 1, files, nfiles);
578 _shisa_lsdir2 (const char *path, const char *realm,
579 char ***files, size_t * nfiles)
581 char *saferealm = escape_filename (realm);
582 char *tmp;
583 int rc;
585 asprintf (&tmp, "%s/%s", path, saferealm);
586 free (saferealm);
588 rc = _shisa_lsdir (tmp, files, nfiles);
590 free (tmp);
592 return rc;
595 static int
596 rm (const char *path)
598 int rc;
600 rc = unlink (path);
601 if (rc != 0)
603 perror (path);
604 return -1;
607 return 0;
611 _shisa_rm4 (const char *path1, const char *realm,
612 const char *principal, const char *path4)
614 char *saferealm = escape_filename (realm);
615 char *safeprincipal = escape_filename (principal);
616 char *tmp;
617 int rc;
619 asprintf (&tmp, "%s/%s/%s/%s", path1, saferealm, safeprincipal, path4);
620 free (saferealm);
621 free (safeprincipal);
623 rc = rm (tmp);
625 free (tmp);
627 return rc;
631 _shisa_rm5 (const char *path1, const char *realm, const char *principal,
632 const char *path4, const char *path5)
634 char *saferealm = escape_filename (realm);
635 char *safeprincipal = escape_filename (principal);
636 char *tmp;
637 int rc;
639 asprintf (&tmp, "%s/%s/%s/%s/%s", path1, saferealm, safeprincipal,
640 path4, path5);
641 free (saferealm);
642 free (safeprincipal);
644 rc = rm (tmp);
646 free (tmp);
648 return rc;
651 FILE *
652 _shisa_fopen4 (const char *path1, const char *realm,
653 const char *principal, const char *path4, const char *mode)
655 char *saferealm = escape_filename (realm);
656 char *safeprincipal = escape_filename (principal);
657 char *tmp;
658 FILE *fh;
660 asprintf (&tmp, "%s/%s/%s/%s", path1, saferealm, safeprincipal, path4);
661 free (saferealm);
662 free (safeprincipal);
664 fh = fopen (tmp, mode);
666 free (tmp);
668 return fh;