"Fossies" - the Fresh Open Source Software Archive

Member "rgdbm-2.1.42/files.c" (20 Jun 2007, 10014 Bytes) of package /linux/privat/old/rgdbm-2.1.42.tgz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "files.c" see the Fossies "Dox" file reference documentation.

    1 #include "config.h"
    2 
    3 #include <stdio.h>
    4 #if STDC_HEADERS
    5 # include <stdlib.h>
    6 # include <stdarg.h>
    7 # include <string.h>
    8 #else
    9 # ifndef HAVE_STRCHR
   10 #  define strchr index
   11 #  define strrchr rindex
   12 # endif
   13 char *strchr (), *strrchr ();
   14 # ifndef HAVE_MEMCPY
   15 #  define memcpy(d, s, n) bcopy ((s), (d), (n))
   16 #  define memmove(d, s, n) bcopy ((s), (d), (n))
   17 # endif
   18 #endif          /* STDC_HEADERS */
   19 
   20 #include <sys/stat.h>           /* for stat struct */
   21 #include <errno.h>              /* for EINVAL etc. */
   22 // won't get far without gdb.h so no test for it
   23 #ifdef HAVE_GDBM_H         /* won't get far without gdbm.h */
   24 # include <gdbm.h>
   25 #elif defined(HAVE_NDBM_H) /* worth checking for ndbm too */
   26 # include <ndbm.h>
   27 #elif defined(HAVE_DBM_H)  /* even worth checking for dbm */
   28 # include <dbm.h>
   29 #endif
   30 
   31 
   32 #include <time.h>               /* for time(2) */
   33 
   34 #include "gdbmd.h"
   35 #include "str.h"
   36 #include "auth.h"
   37 #include "files.h"
   38 
   39 /*
   40  * Get an entry from the database @flf which has been opened as READER
   41  */
   42 static struct stat *
   43 #ifdef HAVE_GDBM_H
   44 fgetflnam (GDBM_FILE flf, char *name)
   45 #elif defined(HAVE_NDBM_H)
   46 fgetflnam (DBM *flf, char *name)
   47 #elif defined(HAVE_DBM_H)
   48 fgetflnam (long dummy, char *name)
   49 #endif
   50 {
   51 
   52     datum key, content;
   53 
   54     if (!name)
   55         return NULL;
   56 
   57     if (*name == '/') {
   58         if (!validpath (name))
   59             return NULL;
   60         // cut off the rgdbm_datadir initial sequence for the registry recovery
   61         name += strlen (rgdbm_datadir) + 1;
   62     }
   63 
   64     key.dsize = strlen (name) + 1;
   65     key.dptr = name;
   66 #ifdef HAVE_GDBM_H
   67     content = gdbm_fetch ((GDBM_FILE)flf, key);
   68 #elif defined(HAVE_NDBM_H)
   69     content = dbm_fetch ((DBM *)flf, key);
   70 #elif defined(HAVE_DBM_H)
   71     content = fetch (key);
   72 #endif
   73 
   74     return (struct stat *) content.dptr;
   75 }
   76 
   77 /*
   78  * Get an entry from the files database
   79  */
   80 struct stat *
   81 getflnam (char *name)
   82 {
   83 
   84 #ifdef HAVE_GDBM_H
   85     GDBM_FILE flf;
   86 #elif defined(HAVE_NDBM_H)
   87     DBM *flf;
   88 #elif defined(HAVE_DBM_H)
   89     long flf;
   90 #endif
   91     static char *files;
   92     struct stat *stat;
   93 
   94     if (!files) {
   95         files = catstr (rgdbm_ctrldir, "/" GDBMD_FILES, NULL);
   96         if (!files)
   97             return NULL;
   98     }
   99 
  100 #ifdef HAVE_GDBM_H
  101     flf = gdbm_open (files, 1024, GDBM_READER, 0400, NULL);
  102 #elif defined(HAVE_NDBM_H)
  103     flf = dbm_open (files, O_RDONLY, 0400);
  104 #elif defined(HAVE_DBM_H)
  105     flf = (dbminit (files) >= 0);
  106 #endif
  107     if (!flf)
  108         return NULL;
  109 
  110     stat = fgetflnam (flf, name);
  111 
  112 #ifdef HAVE_GDBM_H
  113     gdbm_close (flf);
  114 #elif defined(HAVE_NDBM_H)
  115     dbm_close (flf);
  116 #elif defined(HAVE_DBM_H)
  117     dbmclose ();
  118 #endif
  119     return stat;
  120 }
  121 
  122 /*
  123  * break out next line from text file stream @f into @fle buffer, and
  124  * return the name as result.
  125  */
  126 char *
  127 fgettxt(FILE *f, struct stat *fle) {
  128 
  129         int err;
  130         int i0 = 0, i1 = 0, i2 = 0, i3 = 0;
  131         long long x = 0;
  132         char *buf = NULL;
  133 
  134         /* work around for absence of %as format on some archs */
  135         err =
  136          fscanf (f, "%n\t" "name = '%n%*[^']%n' \n%n", &i0, &i1, &i2, &i3);
  137         if (!i2)
  138             return NULL;
  139         buf = malloc (i2 - i1 + 1);
  140         if (!buf)
  141             return NULL;
  142 
  143         err = fseek (f, -(i3 - i0), SEEK_CUR);
  144         if (err < 0)
  145             return NULL;              // horrible wrongness, really
  146         err = fscanf (f, "\t" "name = '%[^']' \n", buf);
  147         /* end work around for absence of %as format on some archs */
  148 
  149         if (err < 1) {
  150             free(buf);
  151             return NULL;
  152         }
  153 
  154         for (;;) {
  155 
  156             if (     ( {
  157                       err =
  158                       (!fle->st_ino) ? fscanf (f, "\t" "ino = %Li \n", &x) : 0;
  159                       if (err >= 1) fle->st_ino = (typeof (fle->st_ino)) x;
  160                       (err >= 1);}
  161                 ) || ( {
  162                       err =
  163                       (!fle->st_mode) ? fscanf (f, "\t" "mode = %Li \n",
  164                                                &x) : 0;
  165                       if (err >= 1) fle->st_mode =
  166                       ((typeof (fle->st_mode)) x & 0777) | S_IFREG;
  167                       (err >= 1);}
  168                 ) || ( {
  169                       err =
  170                       (!fle->st_uid) ? fscanf (f, "\t" "uid = %Li \n", &x) : 0;
  171                       if (err >= 1) fle->st_uid = (typeof (fle->st_uid)) x;
  172                       (err >= 1);}
  173                 ) || ( {
  174                       err =
  175                       (!fle->st_gid) ? fscanf (f, "\t" "gid = %Li \n", &x) : 0;
  176                       if (err >= 1) fle->st_gid = (typeof (fle->st_gid)) x;
  177                       (err >= 1);}
  178                 ) || ( {
  179                       err =
  180                       (!fle->st_blksize) ? fscanf (f, "\t" "blksize = %Li \n",
  181                                                   &x) : 0;
  182                       if (err >= 1) fle->st_blksize =
  183                       (typeof (fle->st_blksize)) x; (err >= 1);}
  184                 ) || ( {
  185                       err =
  186                       (!fle->st_atime) ? fscanf (f, "\t" "atime = %Li \n",
  187                                                 &x) : 0;
  188                       if (err >= 1) fle->st_atime = (typeof (fle->st_atime)) x;
  189                       (err >= 1);}
  190                 ) || ( {
  191                       err =
  192                       (!fle->st_mtime) ? fscanf (f, "\t" "mtime = %Li \n",
  193                                                 &x) : 0;
  194                       if (err >= 1) fle->st_mtime = (typeof (fle->st_mtime)) x;
  195                       (err >= 1);}
  196                 ) || ( {
  197                       err =
  198                       (!fle->st_ctime) ? fscanf (f, "\t" "ctime = %Li \n",
  199                                                 &x) : 0;
  200                       if (err >= 1) fle->st_ctime = (typeof (fle->st_ctime)) x;
  201                       (err >= 1);}
  202                 )
  203              )
  204                 continue;
  205             // no more fields to be had
  206             break;
  207         }
  208 
  209         fscanf (f, "\n");
  210         return buf;
  211 }
  212 
  213 /*
  214  * Add one extra line to the files.txt ascii db. 
  215  * We don't check if it's already in there so be sure to only call
  216  * us at CREATEDB.
  217  */
  218 static int
  219 addtxt (char *name, struct stat *fle)
  220 {
  221 
  222     FILE *f;
  223     static char *filestxt;
  224 
  225     if (!name)
  226         return -EINVAL;
  227 
  228     if (!filestxt) {
  229         filestxt = catstr (rgdbm_ctrldir, "/" GDBMD_FILES_TXT, NULL);
  230         if (!filestxt)
  231             return -ENOMEM;     // give up quietly
  232     }
  233 
  234     if (*name == '/') {
  235         if (!validpath (name))
  236             return -EINVAL;
  237         // cut off the rgdbm_datadir initial sequence for the recording
  238         name += strlen (rgdbm_datadir) + 1;
  239     }
  240 
  241     umask (037);
  242     f = fopen (filestxt, "a+");
  243 
  244     if (!f)
  245         return -EINVAL;         // give up quietly
  246 
  247     fprintf (f,
  248              "name='%s'\n"
  249              "\t" "ino=%-20lu\n"
  250              "\t" "mode=%-#4o\n"
  251              "\t" "uid=%-20lu\n"
  252              "\t" "gid=%-20lu\n"
  253              "\t" "blksize=%-20lu\n"
  254              "\t" "atime=%-20lu\n"
  255              "\t" "mtime=%-20lu\n"
  256              "\t" "ctime=%-20lu\n"
  257              "\n",
  258              name,
  259              (long) fle->st_ino,
  260              (int) fle->st_mode & 0777,
  261              (long) fle->st_uid,
  262              (long) fle->st_gid,
  263              (long) fle->st_blksize,
  264              (long) fle->st_atime,
  265              (long) fle->st_mtime, (long) fle->st_ctime);
  266     fclose (f);
  267     return 0;
  268 }
  269 
  270 /*
  271  * add a new entry to the files database
  272  */
  273 static int
  274 setflnam (char *name, struct stat *fle)
  275 {
  276 
  277 #ifdef HAVE_GDBM_H
  278     GDBM_FILE flf;
  279 #elif defined(HAVE_NDBM_H)
  280     DBM *flf;
  281 #elif defined(HAVE_DBM_H)
  282     long flf;
  283 #endif
  284     int err;
  285     static char *files;
  286 
  287     if (!files) {
  288         files = catstr (rgdbm_ctrldir, "/" GDBMD_FILES, NULL);
  289         if (!files)
  290             return -ENOMEM;
  291     }
  292 
  293 #ifdef HAVE_GDBM_H
  294     flf = gdbm_open (files, 1024, GDBM_WRCREAT, 0640, NULL);
  295 #elif defined(HAVE_NDBM_H)
  296     flf = dbm_open (files, O_RDWR|O_CREAT, 0640);
  297 #elif defined(HAVE_DBM_H)
  298     flf = (dbminit (files) >= 0);
  299 #endif
  300     if (!flf)
  301         return -EINVAL;
  302     err = fsetflnam ((void *)flf, name, fle);
  303 
  304 #ifdef HAVE_GDBM_H
  305     gdbm_close (flf);
  306 #elif defined(HAVE_NDBM_H)
  307     dbm_close (flf);
  308 #elif defined(HAVE_DBM_H)
  309     dbmclose ();
  310 #endif
  311 
  312     return err;
  313 }
  314 
  315 
  316 /*
  317  * Add one datum to the files database and ONE extra line to the files.txt
  318  * ascii db. Use the name only. Invent the details.
  319  *
  320  * We don't check if it's already in there so be sure to only call
  321  * us at CREATEDB.
  322  */
  323 int
  324 register_file (char *name, uid_t uid, gid_t gid, int bs, int mode)
  325 {
  326     int err;
  327     struct stat fle =
  328      {.st_uid = uid, .st_gid = gid, .st_mode = S_IFREG | mode, };
  329 
  330     // don't leave any fields filled with stack data. Fake 'em.
  331     fle.st_mtime = fle.st_ctime = fle.st_atime = time (NULL);
  332     fle.st_blksize = bs;
  333     fle.st_dev = 0;
  334     fle.st_ino = random ();
  335     fle.st_nlink = 1;
  336     fle.st_size = 0;
  337     fle.st_blocks = 0;
  338     err = setflnam (name, &fle);
  339     if (err < 0)
  340         return err;
  341     return addtxt (name, &fle);
  342 }
  343 
  344 /*
  345  * add a new entry to the database @flf opened as WRITER
  346  * The @name is absolute, and will have the datadir leading segment
  347  * chopped off it as it goes into the db.
  348  */
  349 int
  350 fsetflnam (void * flf, char *name, struct stat *fle)
  351 {
  352 
  353     datum key, content;
  354     int err;
  355 
  356     if (!name)
  357         return -EINVAL;
  358 
  359     if (*name == '/') {
  360         if (!validpath (name))
  361             return -EINVAL;
  362         // cut off the rgdbm_datadir initial sequence for the recording
  363         name += strlen (rgdbm_datadir) + 1;
  364     }
  365 
  366     key.dsize = strlen (name) + 1;
  367     key.dptr = name;
  368     content.dsize = sizeof (*fle);
  369     content.dptr = (char *) fle;
  370 
  371     // replace is in case this is an update from files.txt
  372 #ifdef HAVE_GDBM_H
  373     err = gdbm_store ((GDBM_FILE)flf, key, content, GDBM_REPLACE);
  374 #elif defined(HAVE_NDBM_H)
  375     err = dbm_store ((DBM *)flf, key, content, DBM_REPLACE);
  376 #elif defined(HAVE_DBM_H)
  377     err = store (key, content);
  378 #endif
  379     return err;
  380 }
  381 
  382