+/*
+ * Copyright (c) 2001,2002
+ * Traakan, Inc., Los Altos, CA
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice unmodified, this list of conditions, and the following
+ * disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * Project: NDMJOB
+ * Ident: $Id: $
+ *
+ * Description:
+ *
+ */
+
+
+#include "ndmlib.h"
+
+
+
+int
+ndmfhdb_add_file (struct ndmlog *ixlog, int tagc,
+ char *raw_name, ndmp9_file_stat *fstat)
+{
+ char prefix[8];
+ char statbuf[100];
+ char namebuf[NDMOS_CONST_PATH_MAX];
+
+ strcpy (prefix, "DHf");
+ prefix[0] = tagc;
+
+ ndm_fstat_to_str (fstat, statbuf);
+
+ ndmcstr_from_str (raw_name, namebuf, sizeof namebuf);
+
+ ndmlogf (ixlog, prefix, 0, "%s UNIX %s", namebuf, statbuf);
+
+ return 0;
+}
+
+int
+ndmfhdb_add_dir (struct ndmlog *ixlog, int tagc,
+ char *raw_name, ndmp9_u_quad dir_node, ndmp9_u_quad node)
+{
+ char prefix[8];
+ char namebuf[NDMOS_CONST_PATH_MAX];
+
+ strcpy (prefix, "DHd");
+ prefix[0] = tagc;
+
+ ndmcstr_from_str (raw_name, namebuf, sizeof namebuf);
+
+ ndmlogf (ixlog, prefix, 0, "%llu %s UNIX %llu",
+ dir_node, namebuf, node);
+
+ return 0;
+}
+
+int
+ndmfhdb_add_node (struct ndmlog *ixlog, int tagc,
+ ndmp9_u_quad node, ndmp9_file_stat *fstat)
+{
+ char prefix[8];
+ char statbuf[100];
+
+ strcpy (prefix, "DHn");
+ prefix[0] = tagc;
+
+ ndm_fstat_to_str (fstat, statbuf);
+
+ ndmlogf (ixlog, prefix, 0, "%llu UNIX %s", node, statbuf);
+
+ return 0;
+}
+
+int
+ndmfhdb_add_dirnode_root (struct ndmlog *ixlog, int tagc,
+ ndmp9_u_quad root_node)
+{
+ char prefix[8];
+
+ strcpy (prefix, "DHr");
+ prefix[0] = tagc;
+
+ ndmlogf (ixlog, prefix, 0, "%llu", root_node);
+
+ return 0;
+}
+
+
+int
+ndmfhdb_add_fh_info_to_nlist (FILE *fp, ndmp9_name *nlist, int n_nlist)
+{
+ struct ndmfhdb _fhcb, *fhcb = &_fhcb;
+ int i, rc, n_found;
+ ndmp9_file_stat fstat;
+
+ rc = ndmfhdb_open (fp, fhcb);
+ if (rc != 0) {
+ return -31;
+ }
+
+ n_found = 0;
+
+ for (i = 0; i < n_nlist; i++) {
+ char * name = nlist[i].original_path;
+
+ rc = ndmfhdb_lookup (fhcb, name, &fstat);
+ if (rc > 0) {
+ nlist[i].fh_info = fstat.fh_info;
+ if (fstat.fh_info.valid) {
+ n_found++;
+ }
+ }
+ }
+
+ return n_found;
+}
+
+int
+ndmfhdb_open (FILE *fp, struct ndmfhdb *fhcb)
+{
+ int rc;
+
+ NDMOS_MACRO_ZEROFILL (fhcb);
+
+ fhcb->fp = fp;
+
+ rc = ndmfhdb_dirnode_root (fhcb);
+ if (rc > 0) {
+ fhcb->use_dir_node = 1;
+ return 0;
+ }
+
+ rc = ndmfhdb_file_root (fhcb);
+ if (rc > 0) {
+ fhcb->use_dir_node = 0;
+ return 0;
+ }
+
+ return -1;
+}
+
+int
+ndmfhdb_lookup (struct ndmfhdb *fhcb, char *path, ndmp9_file_stat *fstat)
+{
+ if (fhcb->use_dir_node) {
+ return ndmfhdb_dirnode_lookup (fhcb, path, fstat);
+ } else {
+ return ndmfhdb_file_lookup (fhcb, path, fstat);
+ }
+}
+
+int
+ndmfhdb_dirnode_root (struct ndmfhdb *fhcb)
+{
+ int rc, off;
+ char * p;
+ char key[256];
+ char linebuf[2048];
+
+ sprintf (key, "DHr ");
+
+ p = NDMOS_API_STREND(key);
+ off = p - key;
+
+ rc = ndmbstf_first (fhcb->fp, key, linebuf, sizeof linebuf);
+
+ if (rc <= 0) {
+ return rc; /* error or not found */
+ }
+
+ fhcb->root_node = NDMOS_API_STRTOLL (linebuf+off, &p, 0);
+
+ if (*p != 0) {
+ return -10;
+ }
+
+ return 1;
+}
+
+int
+ndmfhdb_dirnode_lookup (struct ndmfhdb *fhcb, char *path,
+ ndmp9_file_stat *fstat)
+{
+ int rc;
+ char * p;
+ char * q;
+ char component[256+128];
+ unsigned long long dir_node;
+ unsigned long long node;
+
+ /* classic path name reduction */
+ node = dir_node = fhcb->root_node;
+ p = path;
+ for (;;) {
+ if (*p == '/') {
+ p++;
+ continue;
+ }
+ if (*p == 0) {
+ break;
+ }
+ q = component;
+ while (*p != 0 && *p != '/') {
+ *q++ = *p++;
+ }
+ *q = 0;
+
+ dir_node = node;
+ rc = ndmfhdb_dir_lookup (fhcb, dir_node, component, &node);
+ if (rc <= 0)
+ return rc; /* error or not found */
+ }
+
+ rc = ndmfhdb_node_lookup (fhcb, node, fstat);
+
+ return rc;
+}
+
+int
+ndmfhdb_dir_lookup (struct ndmfhdb *fhcb, unsigned long long dir_node,
+ char *name, unsigned long long *node_p)
+{
+ int rc, off;
+ char * p;
+ char key[256+128];
+ char linebuf[2048];
+
+ sprintf (key, "DHd %llu ", dir_node);
+ p = NDMOS_API_STREND(key);
+
+ ndmcstr_from_str (name, p, sizeof key - (p-key) - 10);
+
+ strcat (p, " UNIX ");
+
+ p = NDMOS_API_STREND(key);
+ off = p - key;
+
+ rc = ndmbstf_first (fhcb->fp, key, linebuf, sizeof linebuf);
+
+ if (rc <= 0) {
+ return rc; /* error or not found */
+ }
+
+ *node_p = NDMOS_API_STRTOLL (linebuf+off, &p, 0);
+
+ if (*p != 0) {
+ return -10;
+ }
+
+ return 1;
+}
+
+int
+ndmfhdb_node_lookup (struct ndmfhdb *fhcb, unsigned long long node,
+ ndmp9_file_stat *fstat)
+{
+ int rc, off;
+ char * p;
+ char key[128];
+ char linebuf[2048];
+
+ sprintf (key, "DHn %llu UNIX ", node);
+
+ p = NDMOS_API_STREND(key);
+ off = p - key;
+
+
+ rc = ndmbstf_first (fhcb->fp, key, linebuf, sizeof linebuf);
+
+ if (rc <= 0) {
+ return rc; /* error or not found */
+ }
+
+
+ rc = ndm_fstat_from_str (fstat, linebuf + off);
+ if (rc < 0) {
+ return rc;
+ }
+
+ return 1;
+}
+
+int
+ndmfhdb_file_root (struct ndmfhdb *fhcb)
+{
+ int rc;
+ ndmp9_file_stat fstat;
+
+ rc = ndmfhdb_file_lookup (fhcb, "/", &fstat);
+ if (rc > 0) {
+ if (fstat.node.valid)
+ fhcb->root_node = fstat.node.value;
+ }
+
+ return rc;
+}
+
+int
+ndmfhdb_file_lookup (struct ndmfhdb *fhcb, char *path,
+ ndmp9_file_stat *fstat)
+{
+ int rc, off;
+ char * p;
+ char key[2048];
+ char linebuf[2048];
+
+ sprintf (key, "DHf ");
+ p = NDMOS_API_STREND(key);
+
+ ndmcstr_from_str (path, p, sizeof key - (p-key) - 10);
+
+ strcat (p, " UNIX ");
+
+ p = NDMOS_API_STREND(key);
+ off = p - key;
+
+ rc = ndmbstf_first (fhcb->fp, key, linebuf, sizeof linebuf);
+
+ if (rc <= 0) {
+ return rc; /* error or not found */
+ }
+
+ rc = ndm_fstat_from_str (fstat, linebuf + off);
+ if (rc < 0) {
+ return rc;
+ }
+
+ return 1;
+}
+
+
+
+
+/*
+ * Same codes as wraplib.[ch] wrap_parse_fstat_subr()
+ * and wrap_send_fstat_subr().
+ */
+
+char *
+ndm_fstat_to_str (ndmp9_file_stat *fstat, char *buf)
+{
+ char * p = buf;
+
+ *p++ = 'f';
+ switch (fstat->ftype) {
+ case NDMP9_FILE_DIR: *p++ = 'd'; break;
+ case NDMP9_FILE_FIFO: *p++ = 'p'; break;
+ case NDMP9_FILE_CSPEC: *p++ = 'c'; break;
+ case NDMP9_FILE_BSPEC: *p++ = 'b'; break;
+ case NDMP9_FILE_REG: *p++ = '-'; break;
+ case NDMP9_FILE_SLINK: *p++ = 'l'; break;
+ case NDMP9_FILE_SOCK: *p++ = 's'; break;
+ case NDMP9_FILE_REGISTRY: *p++ = 'R'; break;
+ case NDMP9_FILE_OTHER: *p++ = 'o'; break;
+ default: *p++ = '?'; break;
+ }
+
+ if (fstat->mode.valid) {
+ sprintf (p, " m%04lo", fstat->mode.value & 07777);
+ }
+ while (*p) p++;
+
+ if (fstat->uid.valid) {
+ sprintf (p, " u%ld", fstat->uid.value);
+ }
+ while (*p) p++;
+
+ if (fstat->gid.valid) {
+ sprintf (p, " g%ld", fstat->gid.value);
+ }
+ while (*p) p++;
+
+ if (fstat->ftype == NDMP9_FILE_REG
+ || fstat->ftype == NDMP9_FILE_SLINK) {
+ if (fstat->size.valid) {
+ sprintf (p, " s%llu", fstat->size.value);
+ }
+ } else {
+ /* ignore size on other file types */
+ }
+ while (*p) p++;
+
+ /* tar -t can not recover atime/ctime */
+ /* they are also not particularly interesting in the index */
+
+ if (fstat->mtime.valid) {
+ sprintf (p, " tm%lu", fstat->mtime.value);
+ }
+ while (*p) p++;
+
+ if (fstat->fh_info.valid) {
+ sprintf (p, " @%lld", fstat->fh_info.value);
+ }
+ while (*p) p++;
+
+ return buf;
+}
+
+int
+ndm_fstat_from_str (ndmp9_file_stat *fstat, char *buf)
+{
+ char * scan = buf;
+ ndmp9_validity * valid_p;
+
+ NDMOS_MACRO_ZEROFILL (fstat);
+
+ while (*scan) {
+ char * p = scan + 1;
+
+ switch (*scan) {
+ case ' ':
+ scan++;
+ continue;
+
+ case '@': /* fh_info */
+ fstat->fh_info.value = NDMOS_API_STRTOLL (p, &scan, 0);
+ valid_p = &fstat->fh_info.valid;
+ break;
+
+ case 's': /* size */
+ fstat->size.value = NDMOS_API_STRTOLL (p, &scan, 0);
+ valid_p = &fstat->size.valid;
+ break;
+
+ case 'i': /* fileno (inum) */
+ fstat->node.value = NDMOS_API_STRTOLL (p, &scan, 0);
+ valid_p = &fstat->node.valid;
+ break;
+
+ case 'm': /* mode low twelve bits */
+ fstat->mode.value = strtol (p, &scan, 8);
+ valid_p = &fstat->mode.valid;
+ break;
+
+ case 'l': /* link count */
+ fstat->links.value = strtol (p, &scan, 0);
+ valid_p = &fstat->links.valid;
+ break;
+
+ case 'u': /* uid */
+ fstat->uid.value = strtol (p, &scan, 0);
+ valid_p = &fstat->uid.valid;
+ break;
+
+ case 'g': /* gid */
+ fstat->gid.value = strtol (p, &scan, 0);
+ valid_p = &fstat->gid.valid;
+ break;
+
+ case 't': /* one of the times */
+ p = scan+2;
+ switch (scan[1]) {
+ case 'm': /* mtime */
+ fstat->mtime.value = strtol (p, &scan, 0);
+ valid_p = &fstat->mtime.valid;
+ break;
+
+ case 'a': /* atime */
+ fstat->atime.value = strtol (p, &scan, 0);
+ valid_p = &fstat->atime.valid;
+ break;
+
+ case 'c': /* ctime */
+ fstat->ctime.value = strtol (p, &scan, 0);
+ valid_p = &fstat->ctime.valid;
+ break;
+
+ default:
+ return -13;
+ }
+ break;
+
+ case 'f': /* ftype (file type) */
+ switch (scan[1]) {
+ case 'd': fstat->ftype = NDMP9_FILE_DIR; break;
+ case 'p': fstat->ftype = NDMP9_FILE_FIFO; break;
+ case 'c': fstat->ftype = NDMP9_FILE_CSPEC; break;
+ case 'b': fstat->ftype = NDMP9_FILE_BSPEC; break;
+ case '-': fstat->ftype = NDMP9_FILE_REG; break;
+ case 'l': fstat->ftype = NDMP9_FILE_SLINK; break;
+ case 's': fstat->ftype = NDMP9_FILE_SOCK; break;
+ case 'R': fstat->ftype = NDMP9_FILE_REGISTRY; break;
+ case 'o': fstat->ftype = NDMP9_FILE_OTHER; break;
+ default:
+ fstat->ftype = NDMP9_FILE_OTHER;
+ return -15;
+ }
+ scan += 2;
+ valid_p = 0;
+ break;
+
+ default:
+ return -13;
+ }
+
+ if (*scan != ' ' && *scan != 0)
+ return -11;
+
+ if (valid_p)
+ *valid_p = NDMP9_VALIDITY_VALID;
+ }
+
+ return 0;
+}