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 
ndmfhdb_register_callbacks(struct ndmlog * ixlog,struct ndm_fhdb_callbacks * callbacks)40 void ndmfhdb_register_callbacks(struct ndmlog* ixlog,
41                                 struct ndm_fhdb_callbacks* callbacks)
42 {
43   /*
44    * Only allow one register.
45    */
46   if (!ixlog->nfc) {
47     ixlog->nfc = NDMOS_API_MALLOC(sizeof(struct ndm_fhdb_callbacks));
48     if (ixlog->nfc) {
49       memcpy(ixlog->nfc, callbacks, sizeof(struct ndm_fhdb_callbacks));
50     }
51   }
52 }
53 
ndmfhdb_unregister_callbacks(struct ndmlog * ixlog)54 void ndmfhdb_unregister_callbacks(struct ndmlog* ixlog)
55 {
56   if (ixlog->nfc) {
57     NDMOS_API_FREE(ixlog->nfc);
58     ixlog->nfc = NULL;
59   }
60 }
61 
ndmfhdb_add_file(struct ndmlog * ixlog,int tagc,char * raw_name,ndmp9_file_stat * fstat)62 int ndmfhdb_add_file(struct ndmlog* ixlog,
63                      int tagc,
64                      char* raw_name,
65                      ndmp9_file_stat* fstat)
66 {
67   if (ixlog->nfc && ixlog->nfc->add_file) {
68     return ixlog->nfc->add_file(ixlog, tagc, raw_name, fstat);
69   } else {
70     return 0;
71   }
72 }
73 
ndmfhdb_add_dir(struct ndmlog * ixlog,int tagc,char * raw_name,ndmp9_u_quad dir_node,ndmp9_u_quad node)74 int ndmfhdb_add_dir(struct ndmlog* ixlog,
75                     int tagc,
76                     char* raw_name,
77                     ndmp9_u_quad dir_node,
78                     ndmp9_u_quad node)
79 {
80   if (ixlog->nfc && ixlog->nfc->add_dir) {
81     return ixlog->nfc->add_dir(ixlog, tagc, raw_name, dir_node, node);
82   } else {
83     return 0;
84   }
85 }
86 
ndmfhdb_add_node(struct ndmlog * ixlog,int tagc,ndmp9_u_quad node,ndmp9_file_stat * fstat)87 int ndmfhdb_add_node(struct ndmlog* ixlog,
88                      int tagc,
89                      ndmp9_u_quad node,
90                      ndmp9_file_stat* fstat)
91 {
92   if (ixlog->nfc && ixlog->nfc->add_node) {
93     return ixlog->nfc->add_node(ixlog, tagc, node, fstat);
94   } else {
95     return 0;
96   }
97 }
98 
ndmfhdb_add_dirnode_root(struct ndmlog * ixlog,int tagc,ndmp9_u_quad root_node)99 int ndmfhdb_add_dirnode_root(struct ndmlog* ixlog,
100                              int tagc,
101                              ndmp9_u_quad root_node)
102 {
103   if (ixlog->nfc && ixlog->nfc->add_dirnode_root) {
104     return ixlog->nfc->add_dirnode_root(ixlog, tagc, root_node);
105   } else {
106     return 0;
107   }
108 }
109 
ndmfhdb_add_fh_info_to_nlist(FILE * fp,ndmp9_name * nlist,int n_nlist)110 int ndmfhdb_add_fh_info_to_nlist(FILE* fp, ndmp9_name* nlist, int n_nlist)
111 {
112   struct ndmfhdb _fhcb, *fhcb = &_fhcb;
113   int i, rc, n_found;
114   ndmp9_file_stat fstat;
115 
116   rc = ndmfhdb_open(fp, fhcb);
117   if (rc != 0) { return -31; }
118 
119   n_found = 0;
120 
121   for (i = 0; i < n_nlist; i++) {
122     char* name = nlist[i].original_path;
123 
124     rc = ndmfhdb_lookup(fhcb, name, &fstat);
125     if (rc > 0) {
126       nlist[i].fh_info = fstat.fh_info;
127       if (fstat.fh_info.valid) { n_found++; }
128     }
129   }
130 
131   return n_found;
132 }
133 
ndmfhdb_open(FILE * fp,struct ndmfhdb * fhcb)134 int ndmfhdb_open(FILE* fp, struct ndmfhdb* fhcb)
135 {
136   int rc;
137 
138   NDMOS_MACRO_ZEROFILL(fhcb);
139 
140   fhcb->fp = fp;
141 
142   rc = ndmfhdb_dirnode_root(fhcb);
143   if (rc > 0) {
144     fhcb->use_dir_node = 1;
145     return 0;
146   }
147 
148   rc = ndmfhdb_file_root(fhcb);
149   if (rc > 0) {
150     fhcb->use_dir_node = 0;
151     return 0;
152   }
153 
154   return -1;
155 }
156 
ndmfhdb_lookup(struct ndmfhdb * fhcb,char * path,ndmp9_file_stat * fstat)157 int ndmfhdb_lookup(struct ndmfhdb* fhcb, char* path, ndmp9_file_stat* fstat)
158 {
159   if (fhcb->use_dir_node) {
160     return ndmfhdb_dirnode_lookup(fhcb, path, fstat);
161   } else {
162     return ndmfhdb_file_lookup(fhcb, path, fstat);
163   }
164 }
165 
ndmfhdb_dirnode_root(struct ndmfhdb * fhcb)166 int ndmfhdb_dirnode_root(struct ndmfhdb* fhcb)
167 {
168   int rc, off;
169   char* p;
170   char key[256];
171   char linebuf[2048];
172 
173   snprintf(key, sizeof(key), "DHr ");
174 
175   p = NDMOS_API_STREND(key);
176   off = p - key;
177 
178   rc = ndmbstf_first(fhcb->fp, key, linebuf, sizeof linebuf);
179 
180   if (rc <= 0) { return rc; /* error or not found */ }
181 
182   fhcb->root_node = NDMOS_API_STRTOLL(linebuf + off, &p, 0);
183 
184   if (*p != 0) { return -10; }
185 
186   return 1;
187 }
188 
ndmfhdb_dirnode_lookup(struct ndmfhdb * fhcb,char * path,ndmp9_file_stat * fstat)189 int ndmfhdb_dirnode_lookup(struct ndmfhdb* fhcb,
190                            char* path,
191                            ndmp9_file_stat* fstat)
192 {
193   int rc;
194   char* p;
195   char* q;
196   char component[256 + 128];
197   uint64_t dir_node;
198   uint64_t node;
199 
200   /* classic path name reduction */
201   node = dir_node = fhcb->root_node;
202   p = path;
203   for (;;) {
204     if (*p == '/') {
205       p++;
206       continue;
207     }
208     if (*p == 0) { break; }
209     q = component;
210     while (*p != 0 && *p != '/') { *q++ = *p++; }
211     *q = 0;
212 
213     dir_node = node;
214     rc = ndmfhdb_dir_lookup(fhcb, dir_node, component, &node);
215     if (rc <= 0) return rc; /* error or not found */
216   }
217 
218   rc = ndmfhdb_node_lookup(fhcb, node, fstat);
219 
220   return rc;
221 }
222 
ndmfhdb_dir_lookup(struct ndmfhdb * fhcb,uint64_t dir_node,char * name,uint64_t * node_p)223 int ndmfhdb_dir_lookup(struct ndmfhdb* fhcb,
224                        uint64_t dir_node,
225                        char* name,
226                        uint64_t* node_p)
227 {
228   int rc, off;
229   char* p;
230   char key[256 + 128];
231   char linebuf[2048];
232 
233   snprintf(key, sizeof(key), "DHd %llu ", dir_node);
234   p = NDMOS_API_STREND(key);
235 
236   ndmcstr_from_str(name, p, sizeof key - (p - key) - 10);
237 
238   strcat(p, " UNIX ");
239 
240   p = NDMOS_API_STREND(key);
241   off = p - key;
242 
243   rc = ndmbstf_first(fhcb->fp, key, linebuf, sizeof linebuf);
244 
245   if (rc <= 0) { return rc; /* error or not found */ }
246 
247   *node_p = NDMOS_API_STRTOLL(linebuf + off, &p, 0);
248 
249   if (*p != 0) { return -10; }
250 
251   return 1;
252 }
253 
ndmfhdb_node_lookup(struct ndmfhdb * fhcb,uint64_t node,ndmp9_file_stat * fstat)254 int ndmfhdb_node_lookup(struct ndmfhdb* fhcb,
255                         uint64_t node,
256                         ndmp9_file_stat* fstat)
257 {
258   int rc, off;
259   char* p;
260   char key[128];
261   char linebuf[2048];
262 
263   snprintf(key, sizeof(key), "DHn %llu UNIX ", node);
264 
265   p = NDMOS_API_STREND(key);
266   off = p - key;
267 
268 
269   rc = ndmbstf_first(fhcb->fp, key, linebuf, sizeof linebuf);
270 
271   if (rc <= 0) { return rc; /* error or not found */ }
272 
273 
274   rc = ndm_fstat_from_str(fstat, linebuf + off);
275   if (rc < 0) { return rc; }
276 
277   return 1;
278 }
279 
ndmfhdb_file_root(struct ndmfhdb * fhcb)280 int ndmfhdb_file_root(struct ndmfhdb* fhcb)
281 {
282   int rc;
283   ndmp9_file_stat fstat;
284 
285   rc = ndmfhdb_file_lookup(fhcb, "/", &fstat);
286   if (rc > 0) {
287     if (fstat.node.valid) fhcb->root_node = fstat.node.value;
288   }
289 
290   return rc;
291 }
292 
ndmfhdb_file_lookup(struct ndmfhdb * fhcb,char * path,ndmp9_file_stat * fstat)293 int ndmfhdb_file_lookup(struct ndmfhdb* fhcb,
294                         char* path,
295                         ndmp9_file_stat* fstat)
296 {
297   int rc, off;
298   char* p;
299   char key[2048];
300   char linebuf[2048];
301 
302   snprintf(key, sizeof(key), "DHf ");
303   p = NDMOS_API_STREND(key);
304 
305   ndmcstr_from_str(path, p, sizeof key - (p - key) - 10);
306 
307   strcat(p, " UNIX ");
308 
309   p = NDMOS_API_STREND(key);
310   off = p - key;
311 
312   rc = ndmbstf_first(fhcb->fp, key, linebuf, sizeof linebuf);
313 
314   if (rc <= 0) { return rc; /* error or not found */ }
315 
316   rc = ndm_fstat_from_str(fstat, linebuf + off);
317   if (rc < 0) { return rc; }
318 
319   return 1;
320 }
321 
322 /*
323  * Same codes as wraplib.[ch] wrap_parse_fstat_subr()
324  * and wrap_send_fstat_subr().
325  */
ndm_fstat_to_str(ndmp9_file_stat * fstat,char * buf)326 char* ndm_fstat_to_str(ndmp9_file_stat* fstat, char* buf)
327 {
328   char* p = buf;
329 
330   *p++ = 'f';
331   switch (fstat->ftype) {
332     case NDMP9_FILE_DIR:
333       *p++ = 'd';
334       break;
335     case NDMP9_FILE_FIFO:
336       *p++ = 'p';
337       break;
338     case NDMP9_FILE_CSPEC:
339       *p++ = 'c';
340       break;
341     case NDMP9_FILE_BSPEC:
342       *p++ = 'b';
343       break;
344     case NDMP9_FILE_REG:
345       *p++ = '-';
346       break;
347     case NDMP9_FILE_SLINK:
348       *p++ = 'l';
349       break;
350     case NDMP9_FILE_SOCK:
351       *p++ = 's';
352       break;
353     case NDMP9_FILE_REGISTRY:
354       *p++ = 'R';
355       break;
356     case NDMP9_FILE_OTHER:
357       *p++ = 'o';
358       break;
359     default:
360       *p++ = '?';
361       break;
362   }
363 
364   if (fstat->mode.valid) { sprintf(p, " m%04lo", fstat->mode.value & 07777); }
365   while (*p) p++;
366 
367   if (fstat->uid.valid) { sprintf(p, " u%ld", fstat->uid.value); }
368   while (*p) p++;
369 
370   if (fstat->gid.valid) { sprintf(p, " g%ld", fstat->gid.value); }
371   while (*p) p++;
372 
373   if (fstat->ftype == NDMP9_FILE_REG || fstat->ftype == NDMP9_FILE_SLINK) {
374     if (fstat->size.valid) { sprintf(p, " s%llu", fstat->size.value); }
375   } else {
376     /* ignore size on other file types */
377   }
378   while (*p) p++;
379 
380   /* tar -t can not recover atime/ctime */
381   /* they are also not particularly interesting in the index */
382 
383   if (fstat->mtime.valid) { sprintf(p, " tm%lu", fstat->mtime.value); }
384   while (*p) p++;
385 
386   if (fstat->fh_info.valid) { sprintf(p, " @%lld", fstat->fh_info.value); }
387   while (*p) p++;
388 
389   return buf;
390 }
391 
ndm_fstat_from_str(ndmp9_file_stat * fstat,char * buf)392 int ndm_fstat_from_str(ndmp9_file_stat* fstat, char* buf)
393 {
394   char* scan = buf;
395   ndmp9_validity* valid_p;
396 
397   NDMOS_MACRO_ZEROFILL(fstat);
398 
399   while (*scan) {
400     char* p = scan + 1;
401 
402     switch (*scan) {
403       case ' ':
404         scan++;
405         continue;
406 
407       case '@': /* fh_info */
408         fstat->fh_info.value = NDMOS_API_STRTOLL(p, &scan, 0);
409         valid_p = &fstat->fh_info.valid;
410         break;
411 
412       case 's': /* size */
413         fstat->size.value = NDMOS_API_STRTOLL(p, &scan, 0);
414         valid_p = &fstat->size.valid;
415         break;
416 
417       case 'i': /* fileno (inum) */
418         fstat->node.value = NDMOS_API_STRTOLL(p, &scan, 0);
419         valid_p = &fstat->node.valid;
420         break;
421 
422       case 'm': /* mode low twelve bits */
423         fstat->mode.value = strtol(p, &scan, 8);
424         valid_p = &fstat->mode.valid;
425         break;
426 
427       case 'l': /* link count */
428         fstat->links.value = strtol(p, &scan, 0);
429         valid_p = &fstat->links.valid;
430         break;
431 
432       case 'u': /* uid */
433         fstat->uid.value = strtol(p, &scan, 0);
434         valid_p = &fstat->uid.valid;
435         break;
436 
437       case 'g': /* gid */
438         fstat->gid.value = strtol(p, &scan, 0);
439         valid_p = &fstat->gid.valid;
440         break;
441 
442       case 't': /* one of the times */
443         p = scan + 2;
444         switch (scan[1]) {
445           case 'm': /* mtime */
446             fstat->mtime.value = strtol(p, &scan, 0);
447             valid_p = &fstat->mtime.valid;
448             break;
449 
450           case 'a': /* atime */
451             fstat->atime.value = strtol(p, &scan, 0);
452             valid_p = &fstat->atime.valid;
453             break;
454 
455           case 'c': /* ctime */
456             fstat->ctime.value = strtol(p, &scan, 0);
457             valid_p = &fstat->ctime.valid;
458             break;
459 
460           default:
461             return -13;
462         }
463         break;
464 
465       case 'f': /* ftype (file type) */
466         switch (scan[1]) {
467           case 'd':
468             fstat->ftype = NDMP9_FILE_DIR;
469             break;
470           case 'p':
471             fstat->ftype = NDMP9_FILE_FIFO;
472             break;
473           case 'c':
474             fstat->ftype = NDMP9_FILE_CSPEC;
475             break;
476           case 'b':
477             fstat->ftype = NDMP9_FILE_BSPEC;
478             break;
479           case '-':
480             fstat->ftype = NDMP9_FILE_REG;
481             break;
482           case 'l':
483             fstat->ftype = NDMP9_FILE_SLINK;
484             break;
485           case 's':
486             fstat->ftype = NDMP9_FILE_SOCK;
487             break;
488           case 'R':
489             fstat->ftype = NDMP9_FILE_REGISTRY;
490             break;
491           case 'o':
492             fstat->ftype = NDMP9_FILE_OTHER;
493             break;
494           default:
495             fstat->ftype = NDMP9_FILE_OTHER;
496             return -15;
497         }
498         scan += 2;
499         valid_p = 0;
500         break;
501 
502       default:
503         return -13;
504     }
505 
506     if (*scan != ' ' && *scan != 0) return -11;
507 
508     if (valid_p) *valid_p = NDMP9_VALIDITY_VALID;
509   }
510 
511   return 0;
512 }
513