Imported Upstream version 3.1.0
[debian/amanda] / ndmp-src / ndml_fhdb.c
1 /*
2  * Copyright (c) 2001,2002
3  *      Traakan, Inc., Los Altos, CA
4  *      All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  * 1. Redistributions of source code must retain the above copyright
10  *    notice unmodified, this list of conditions, and the following
11  *    disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28
29 /*
30  * Project:  NDMJOB
31  * Ident:    $Id: $
32  *
33  * Description:
34  *
35  */
36
37
38 #include "ndmlib.h"
39
40
41
42 int
43 ndmfhdb_add_file (struct ndmlog *ixlog, int tagc,
44   char *raw_name, ndmp9_file_stat *fstat)
45 {
46         char            prefix[8];
47         char            statbuf[100];
48         char            namebuf[NDMOS_CONST_PATH_MAX];
49
50         strcpy (prefix, "DHf");
51         prefix[0] = tagc;
52
53         ndm_fstat_to_str (fstat, statbuf);
54
55         ndmcstr_from_str (raw_name, namebuf, sizeof namebuf);
56
57         ndmlogf (ixlog, prefix, 0, "%s UNIX %s", namebuf, statbuf);
58
59         return 0;
60 }
61
62 int
63 ndmfhdb_add_dir (struct ndmlog *ixlog, int tagc,
64   char *raw_name, ndmp9_u_quad dir_node, ndmp9_u_quad node)
65 {
66         char            prefix[8];
67         char            namebuf[NDMOS_CONST_PATH_MAX];
68
69         strcpy (prefix, "DHd");
70         prefix[0] = tagc;
71
72         ndmcstr_from_str (raw_name, namebuf, sizeof namebuf);
73
74         ndmlogf (ixlog, prefix, 0, "%llu %s UNIX %llu",
75                 dir_node, namebuf, node);
76
77         return 0;
78 }
79
80 int
81 ndmfhdb_add_node (struct ndmlog *ixlog, int tagc,
82   ndmp9_u_quad node, ndmp9_file_stat *fstat)
83 {
84         char            prefix[8];
85         char            statbuf[100];
86
87         strcpy (prefix, "DHn");
88         prefix[0] = tagc;
89
90         ndm_fstat_to_str (fstat, statbuf);
91
92         ndmlogf (ixlog, prefix, 0, "%llu UNIX %s", node, statbuf);
93
94         return 0;
95 }
96
97 int
98 ndmfhdb_add_dirnode_root (struct ndmlog *ixlog, int tagc,
99   ndmp9_u_quad root_node)
100 {
101         char            prefix[8];
102
103         strcpy (prefix, "DHr");
104         prefix[0] = tagc;
105
106         ndmlogf (ixlog, prefix, 0, "%llu", root_node);
107
108         return 0;
109 }
110
111
112 int
113 ndmfhdb_add_fh_info_to_nlist (FILE *fp, ndmp9_name *nlist, int n_nlist)
114 {
115         struct ndmfhdb          _fhcb, *fhcb = &_fhcb;
116         int                     i, rc, n_found;
117         ndmp9_file_stat         fstat;
118
119         rc = ndmfhdb_open (fp, fhcb);
120         if (rc != 0) {
121                 return -31;
122         }
123
124         n_found = 0;
125
126         for (i = 0; i < n_nlist; i++) {
127                 char *          name = nlist[i].original_path;
128
129                 rc = ndmfhdb_lookup (fhcb, name, &fstat);
130                 if (rc > 0) {
131                         nlist[i].fh_info = fstat.fh_info;
132                         if (fstat.fh_info.valid) {
133                                 n_found++;
134                         }
135                 }
136         }
137
138         return n_found;
139 }
140
141 int
142 ndmfhdb_open (FILE *fp, struct ndmfhdb *fhcb)
143 {
144         int             rc;
145
146         NDMOS_MACRO_ZEROFILL (fhcb);
147
148         fhcb->fp = fp;
149
150         rc = ndmfhdb_dirnode_root (fhcb);
151         if (rc > 0) {
152                 fhcb->use_dir_node = 1;
153                 return 0;
154         }
155
156         rc = ndmfhdb_file_root (fhcb);
157         if (rc > 0) {
158                 fhcb->use_dir_node = 0;
159                 return 0;
160         }
161
162         return -1;
163 }
164
165 int
166 ndmfhdb_lookup (struct ndmfhdb *fhcb, char *path, ndmp9_file_stat *fstat)
167 {
168         if (fhcb->use_dir_node) {
169                 return ndmfhdb_dirnode_lookup (fhcb, path, fstat);
170         } else {
171                 return ndmfhdb_file_lookup (fhcb, path, fstat);
172         }
173 }
174
175 int
176 ndmfhdb_dirnode_root (struct ndmfhdb *fhcb)
177 {
178         int             rc, off;
179         char *          p;
180         char            key[256];
181         char            linebuf[2048];
182
183         sprintf (key, "DHr ");
184
185         p = NDMOS_API_STREND(key);
186         off = p - key;
187
188         rc = ndmbstf_first (fhcb->fp, key, linebuf, sizeof linebuf);
189
190         if (rc <= 0) {
191                 return rc;      /* error or not found */
192         }
193
194         fhcb->root_node = NDMOS_API_STRTOLL (linebuf+off, &p, 0);
195
196         if (*p != 0) {
197                 return -10;
198         }
199
200         return 1;
201 }
202
203 int
204 ndmfhdb_dirnode_lookup (struct ndmfhdb *fhcb, char *path,
205   ndmp9_file_stat *fstat)
206 {
207         int                     rc;
208         char *                  p;
209         char *                  q;
210         char                    component[256+128];
211         unsigned long long      dir_node;
212         unsigned long long      node;
213
214         /* classic path name reduction */
215         node = dir_node = fhcb->root_node;
216         p = path;
217         for (;;) {
218                 if (*p == '/') {
219                         p++;
220                         continue;
221                 }
222                 if (*p == 0) {
223                         break;
224                 }
225                 q = component;
226                 while (*p != 0 && *p != '/') {
227                         *q++ = *p++;
228                 }
229                 *q = 0;
230
231                 dir_node = node;
232                 rc = ndmfhdb_dir_lookup (fhcb, dir_node, component, &node);
233                 if (rc <= 0)
234                         return rc;      /* error or not found */
235         }
236
237         rc = ndmfhdb_node_lookup (fhcb, node, fstat);
238
239         return rc;
240 }
241
242 int
243 ndmfhdb_dir_lookup (struct ndmfhdb *fhcb, unsigned long long dir_node,
244   char *name, unsigned long long *node_p)
245 {
246         int             rc, off;
247         char *          p;
248         char            key[256+128];
249         char            linebuf[2048];
250
251         sprintf (key, "DHd %llu ", dir_node);
252         p = NDMOS_API_STREND(key);
253
254         ndmcstr_from_str (name, p, sizeof key - (p-key) - 10);
255
256         strcat (p, " UNIX ");
257
258         p = NDMOS_API_STREND(key);
259         off = p - key;
260
261         rc = ndmbstf_first (fhcb->fp, key, linebuf, sizeof linebuf);
262
263         if (rc <= 0) {
264                 return rc;      /* error or not found */
265         }
266
267         *node_p = NDMOS_API_STRTOLL (linebuf+off, &p, 0);
268
269         if (*p != 0) {
270                 return -10;
271         }
272
273         return 1;
274 }
275
276 int
277 ndmfhdb_node_lookup (struct ndmfhdb *fhcb, unsigned long long node,
278   ndmp9_file_stat *fstat)
279 {
280         int             rc, off;
281         char *          p;
282         char            key[128];
283         char            linebuf[2048];
284
285         sprintf (key, "DHn %llu UNIX ", node);
286
287         p = NDMOS_API_STREND(key);
288         off = p - key;
289
290
291         rc = ndmbstf_first (fhcb->fp, key, linebuf, sizeof linebuf);
292
293         if (rc <= 0) {
294                 return rc;      /* error or not found */
295         }
296
297
298         rc = ndm_fstat_from_str (fstat, linebuf + off);
299         if (rc < 0) {
300                 return rc;
301         }
302
303         return 1;
304 }
305
306 int
307 ndmfhdb_file_root (struct ndmfhdb *fhcb)
308 {
309         int                     rc;
310         ndmp9_file_stat         fstat;
311
312         rc = ndmfhdb_file_lookup (fhcb, "/", &fstat);
313         if (rc > 0) {
314                 if (fstat.node.valid)
315                         fhcb->root_node = fstat.node.value;
316         }
317
318         return rc;
319 }
320
321 int
322 ndmfhdb_file_lookup (struct ndmfhdb *fhcb, char *path,
323   ndmp9_file_stat *fstat)
324 {
325         int             rc, off;
326         char *          p;
327         char            key[2048];
328         char            linebuf[2048];
329
330         sprintf (key, "DHf ");
331         p = NDMOS_API_STREND(key);
332
333         ndmcstr_from_str (path, p, sizeof key - (p-key) - 10);
334
335         strcat (p, " UNIX ");
336
337         p = NDMOS_API_STREND(key);
338         off = p - key;
339
340         rc = ndmbstf_first (fhcb->fp, key, linebuf, sizeof linebuf);
341
342         if (rc <= 0) {
343                 return rc;      /* error or not found */
344         }
345
346         rc = ndm_fstat_from_str (fstat, linebuf + off);
347         if (rc < 0) {
348                 return rc;
349         }
350
351         return 1;
352 }
353
354
355
356
357 /*
358  * Same codes as wraplib.[ch] wrap_parse_fstat_subr()
359  * and wrap_send_fstat_subr().
360  */
361
362 char *
363 ndm_fstat_to_str (ndmp9_file_stat *fstat, char *buf)
364 {
365         char *                  p = buf;
366
367         *p++ = 'f';
368         switch (fstat->ftype) {
369         case NDMP9_FILE_DIR:    *p++ = 'd';     break;
370         case NDMP9_FILE_FIFO:   *p++ = 'p';     break;
371         case NDMP9_FILE_CSPEC:  *p++ = 'c';     break;
372         case NDMP9_FILE_BSPEC:  *p++ = 'b';     break;
373         case NDMP9_FILE_REG:    *p++ = '-';     break;
374         case NDMP9_FILE_SLINK:  *p++ = 'l';     break;
375         case NDMP9_FILE_SOCK:   *p++ = 's';     break;
376         case NDMP9_FILE_REGISTRY: *p++ = 'R';   break;
377         case NDMP9_FILE_OTHER:  *p++ = 'o';     break;
378         default:                *p++ = '?';     break;
379         }
380
381         if (fstat->mode.valid) {
382                 sprintf (p, " m%04lo", fstat->mode.value & 07777);
383         }
384         while (*p) p++;
385
386         if (fstat->uid.valid) {
387                 sprintf (p, " u%ld", fstat->uid.value);
388         }
389         while (*p) p++;
390
391         if (fstat->gid.valid) {
392                 sprintf (p, " g%ld", fstat->gid.value);
393         }
394         while (*p) p++;
395
396         if (fstat->ftype == NDMP9_FILE_REG
397          || fstat->ftype == NDMP9_FILE_SLINK) {
398                 if (fstat->size.valid) {
399                         sprintf (p, " s%llu", fstat->size.value);
400                 }
401         } else {
402                 /* ignore size on other file types */
403         }
404         while (*p) p++;
405
406         /* tar -t can not recover atime/ctime */
407         /* they are also not particularly interesting in the index */
408
409         if (fstat->mtime.valid) {
410                 sprintf (p, " tm%lu", fstat->mtime.value);
411         }
412         while (*p) p++;
413
414         if (fstat->fh_info.valid) {
415                 sprintf (p, " @%lld", fstat->fh_info.value);
416         }
417         while (*p) p++;
418
419         return buf;
420 }
421
422 int
423 ndm_fstat_from_str (ndmp9_file_stat *fstat, char *buf)
424 {
425         char *                  scan = buf;
426         ndmp9_validity *        valid_p;
427
428         NDMOS_MACRO_ZEROFILL (fstat);
429
430         while (*scan) {
431                 char *          p = scan + 1;
432
433                 switch (*scan) {
434                 case ' ':
435                         scan++;
436                         continue;
437
438                 case '@':       /* fh_info */
439                         fstat->fh_info.value = NDMOS_API_STRTOLL (p, &scan, 0);
440                         valid_p = &fstat->fh_info.valid;
441                         break;
442
443                 case 's':       /* size */
444                         fstat->size.value = NDMOS_API_STRTOLL (p, &scan, 0);
445                         valid_p = &fstat->size.valid;
446                         break;
447
448                 case 'i':       /* fileno (inum) */
449                         fstat->node.value = NDMOS_API_STRTOLL (p, &scan, 0);
450                         valid_p = &fstat->node.valid;
451                         break;
452
453                 case 'm':       /* mode low twelve bits */
454                         fstat->mode.value = strtol (p, &scan, 8);
455                         valid_p = &fstat->mode.valid;
456                         break;
457
458                 case 'l':       /* link count */
459                         fstat->links.value = strtol (p, &scan, 0);
460                         valid_p = &fstat->links.valid;
461                         break;
462
463                 case 'u':       /* uid */
464                         fstat->uid.value = strtol (p, &scan, 0);
465                         valid_p = &fstat->uid.valid;
466                         break;
467
468                 case 'g':       /* gid */
469                         fstat->gid.value = strtol (p, &scan, 0);
470                         valid_p = &fstat->gid.valid;
471                         break;
472
473                 case 't':               /* one of the times */
474                         p = scan+2;
475                         switch (scan[1]) {
476                         case 'm':       /* mtime */
477                                 fstat->mtime.value = strtol (p, &scan, 0);
478                                 valid_p = &fstat->mtime.valid;
479                                 break;
480
481                         case 'a':       /* atime */
482                                 fstat->atime.value = strtol (p, &scan, 0);
483                                 valid_p = &fstat->atime.valid;
484                                 break;
485
486                         case 'c':       /* ctime */
487                                 fstat->ctime.value = strtol (p, &scan, 0);
488                                 valid_p = &fstat->ctime.valid;
489                                 break;
490
491                         default:
492                                 return -13;
493                         }
494                         break;
495
496                 case 'f':       /* ftype (file type) */
497                         switch (scan[1]) {
498                         case 'd': fstat->ftype = NDMP9_FILE_DIR; break;
499                         case 'p': fstat->ftype = NDMP9_FILE_FIFO; break;
500                         case 'c': fstat->ftype = NDMP9_FILE_CSPEC; break;
501                         case 'b': fstat->ftype = NDMP9_FILE_BSPEC; break;
502                         case '-': fstat->ftype = NDMP9_FILE_REG; break;
503                         case 'l': fstat->ftype = NDMP9_FILE_SLINK; break;
504                         case 's': fstat->ftype = NDMP9_FILE_SOCK; break;
505                         case 'R': fstat->ftype = NDMP9_FILE_REGISTRY; break;
506                         case 'o': fstat->ftype = NDMP9_FILE_OTHER; break;
507                         default:
508                                 fstat->ftype = NDMP9_FILE_OTHER;
509                                 return -15;
510                         }
511                         scan += 2;
512                         valid_p = 0;
513                         break;
514
515                 default:
516                         return -13;
517                 }
518
519                 if (*scan != ' ' && *scan != 0)
520                         return -11;
521
522                 if (valid_p)
523                         *valid_p = NDMP9_VALIDITY_VALID;
524         }
525
526         return 0;
527 }