home *** CD-ROM | disk | FTP | other *** search
/ Black Box 4 / BlackBox.cdr / lan / soss.arj / SRC / INODES.C < prev    next >
C/C++ Source or Header  |  1991-02-22  |  21KB  |  743 lines

  1. /*
  2.  *  inodes.c --
  3.  *      Index node implementation for PC NFS file server.  The server
  4.  *      builds its view of the filesystem everytime a lookup call is
  5.  *      generated for a file, and initially when the file system export
  6.  *      list is parsed.  This package handles DOS and UNIX style pathnames.
  7.  *
  8.  *  Author:
  9.  *      See-Mong Tan
  10.  *  Modified by:
  11.  *    Rich Braun @ Kronos
  12.  */
  13.  
  14. #include "common.h"
  15.  
  16. /* forward declaration of local procedures */
  17. static void getcomp();
  18. static u_long insertapath();
  19. static u_long newinodeno();
  20. static bool_t _inremnode();
  21.  
  22. /* the inode dump file */
  23. #define INODEFILE "inode.dmp"
  24.  
  25. /* Number of inodes and attributes entries to store in memory */
  26. #define NUMINODES 12000
  27. #define NUMACACHE 400
  28.  
  29. /* the global inode file pointer */
  30. static FILE *inodefp;
  31.  
  32. /* last inode number assigned - starting from 2, 1 is root directory of all */
  33. static u_long lastinodeno = 2;
  34.  
  35.   /* The attributes cache.  Each inode is optionally associated        */
  36.   /* with a cache entry containing its file attributes (owner UID,    */
  37.   /* size, creation date, etc.)  The cache is fixed in size and is      */
  38.   /* stored in the form of a doubly-linked list, with the most recently */
  39.   /* accessed item at the head and the oldest at the tail.  If the      */
  40.   /* cache is full, the oldest item is disassociated with its inode     */
  41.   /* and it is moved to the had and associated with a new inode.        */
  42.  
  43. typedef struct _acache {
  44.     struct _acache far  *next;
  45.     struct _acache far  *prev;
  46.     u_short             inode;
  47.     struct nfsfattr     fattr;
  48. } Acache_t;
  49.  
  50. static Acache_t far *attrcache;        /* Head and tail pointers */
  51. static Acache_t far *attrfree;
  52.  
  53.   /* The inode cache. */
  54. typedef struct DIRNODE {
  55.     char name[MAXFILENAMELEN];    /* dos file name */
  56.     u_char  fsid;            /* drive of file (1 = A:) */
  57.     u_short inode;            /* its inode number */
  58.     u_short    top : 1,        /* Flag indicating top of filesystem*/
  59.         gen : 14;        /* generation count */
  60.     struct DIRNODE far *next;    /* next file in same directory */
  61.     struct DIRNODE far *subdir;    /* ptr to subdirectory entries */
  62.     struct DIRNODE far *parent;    /* ptr to parent directory */
  63.     Acache_t far *attr;        /* file attributes, if known */
  64. } Dir_t;
  65.  
  66.   /* the directory structure begins here */
  67. static Dir_t far *RootDir = NULL;
  68.  
  69.   /* the inode table - list of directory node pointers  */
  70.   /* allocated on initialization            */
  71. typedef Dir_t far *Inode_t;
  72.  
  73. Inode_t far *InodeTable;
  74. static u_short gencount = 1;
  75.  
  76. /*
  77.  *  bool_t inode_init() --
  78.  *      Initializes the inode module.  Reads the previous (if any) inodes
  79.  *      created and adds them to the directory tree.  Has a very simple
  80.  *      minded export file parser.
  81.  */
  82. bool_t inode_init()
  83. {
  84.     FILE *fp;
  85.     char line[300];
  86.     char path[MAXPATHNAMELEN];
  87.     int i;
  88.  
  89.     /* Initialize inode table */
  90.  
  91.     if ((InodeTable = (Inode_t far *) _fmalloc (NUMINODES * 4)) == NULL)
  92.       return FALSE;
  93.  
  94.     /* Initialize attributes cache */
  95.  
  96.     if ((attrcache = (Acache_t far *) _fmalloc (NUMACACHE *
  97.                     sizeof (Acache_t))) == NULL)
  98.       return FALSE;
  99.  
  100.     /* The 0th entry is the list head; the free list starts at  */
  101.     /* entry 1.                            */
  102.     attrcache->next = attrcache->prev = attrcache;
  103.     attrcache->inode = -1;
  104.     attrfree = &attrcache[1];
  105.  
  106.     for (i = 0; i < NUMACACHE-2; i++)
  107.     attrfree[i].next = &attrfree[i+1];
  108.     attrfree[i].next = NULL;
  109.  
  110.     /* Read export list to build initial inode tree */
  111.     if ((fp = fopen(EXPORTS, "r")) == NULL)
  112.       return FALSE;
  113.     while(fgets(line, MAXPATHNAMELEN -1, fp) == line) {
  114.     u_long nodeid;
  115.  
  116.     /* get the pathname alone */
  117.     sscanf (line, "%s", path);
  118.  
  119.     /* Truncate trailing backslash for root directory */
  120.     if (path[1] == ':' && path[3] == '\0')
  121.       path[2] = '\0';
  122.  
  123.     /* Skip if shorter than 2 characters */
  124.     if (strlen(path) < 2) 
  125.       break;
  126.  
  127.     nodeid = insertapath(path, (Dir_t far *) NULL,
  128.                  (Dir_t far * far *) &RootDir);
  129.  
  130.     /* Set the top-of-filesystem flag */
  131.     InodeTable[nodeid]->top = TRUE;
  132.     }
  133.     (void) fclose(fp);
  134.  
  135.     /* rebuild old filesystem tree */
  136.     /* open for reading and appending */
  137.     if ((fp = fopen(INODEFILE, "a+")) == NULL)
  138.       return FALSE;
  139.  
  140.     while(fscanf(fp, "%s", path) != EOF) {
  141.     if (path[0] != '-')
  142.       (void) insertapath(path, (Dir_t far *) NULL,
  143.                  (Dir_t far * far *) &RootDir);
  144.     else {
  145.         u_long nodeid;
  146.  
  147.         sscanf (path+1, "%ld", &nodeid);
  148.         (void) _inremnode (nodeid);
  149.     }
  150.     }
  151.     (void) fclose(fp);
  152.     return TRUE;
  153. }
  154.  
  155. /*        
  156.  *  void getcomp(char *comp, char **path) --
  157.  *      Gets component name of *path and puts it in comp, and advances
  158.  *      *path to beginning of next component.  Handles UNIX or DOS style
  159.  *      pathnames.
  160.  */
  161. /* Valid characters in a DOS name are:  ! #$%&'() -. @ ^_` {}~ */
  162.  
  163. u_char inchvalid[95] = {   1, 0, 1, 1, 1, 1, 1,       /* ! thru ' */
  164.             1, 1, 0, 0, 0, 1, 1, 0,     /* ( thru / */
  165.             1, 1, 1, 1, 1, 1, 1, 1,        /* 0 thru 7 */
  166.             1, 1, 0, 0, 0, 0, 0, 0,        /* 8 thru ? */
  167.             1, 1, 1, 1, 1, 1, 1, 1,        /* @ thru G */
  168.             1, 1, 1, 1, 1, 1, 1, 1,        /* H thru O */
  169.             1, 1, 1, 1, 1, 1, 1, 1,        /* P thru W */
  170.             1, 1, 1, 0, 0, 0, 1, 1,        /* X thru _ */
  171.             1, 1, 1, 1, 1, 1, 1, 1,        /* ` thru g */
  172.             1, 1, 1, 1, 1, 1, 1, 1,        /* h thru o */
  173.             1, 1, 1, 1, 1, 1, 1, 1,        /* p thru w */
  174.             1, 1, 1, 1, 0, 1, 1, 0};    /* x thru DEL */
  175.  
  176. static void getcomp(comp, path)
  177.      char *comp;
  178.      char **path;
  179. {
  180.     if (! (**path > ' ' && !(**path & 0x80) && inchvalid[**path - '!']))
  181.       (*path)++;
  182.     while(**path > ' ' && !(**path & 0x80) && inchvalid[**path - '!']) {
  183.     *comp++ = **path;
  184.     (*path)++;
  185.     }
  186.     if (**path == ':')
  187.       (*path)++;
  188.     *comp = '\0';
  189. }
  190.  
  191. /*
  192.  *  Dir_t *makenewdirnode(char *name, Dir_t far *parent) --
  193.  *      Returns new directory node initialized with name.
  194.  */
  195. Dir_t far *makenewdirnode(name, parent)
  196.      char *name;
  197.      Dir_t far *parent;
  198. {
  199.     Dir_t far *new;
  200.  
  201.     new = (Dir_t far *) _fmalloc(sizeof(Dir_t));
  202.     if (new == (Dir_t far *) NULL) {
  203.     (void) fprintf(stderr, "nfs: out of memory\n");
  204.     abort();
  205.     }
  206.     (void) bcopy_nf(name, new->name, MAXFILENAMELEN);
  207.     new->inode = (u_short) newinodeno();
  208.     new->parent = parent;
  209.     new->next = new->subdir = (Dir_t far *) NULL;
  210.     new->attr = (struct nfsfattr far *) NULL;
  211.     new->top  = FALSE;
  212.     new->gen  = gencount++;
  213.     if (parent == (Dir_t far *) NULL)
  214.       new->fsid = *name - (islower(*name) ? 'a' : 'A') + 1;
  215.     else
  216.       new->fsid = parent->fsid;
  217.     InodeTable[new->inode] = new;
  218.     return new;
  219. }
  220.  
  221. /*
  222.  *  void inremnode(u_long inode) --
  223.  *      Removes the indicated node.
  224.  */
  225. void inremnode (inode)
  226.      u_long inode;
  227. {
  228.     Dir_t far *dirp;
  229.  
  230.     if (_inremnode (inode)) {
  231.     if (inodefp == (FILE *) NULL)
  232.       inodefp = fopen(INODEFILE, "a");
  233.     (void) fprintf(inodefp, "-%ld\n", inode);    /* add to inode file */
  234.     }
  235. /*   else {
  236.  *    DBGPRT1 (nfserr, "inremnode %ld failed", inode);
  237.  *  }
  238.  */
  239. }
  240.  
  241. /*
  242.  *  bool_t _inremnode(u_long inode) --
  243.  *      Prunes an inode from the tree.
  244.  */
  245. static bool_t _inremnode (inode)
  246.      u_long inode;
  247. {
  248.     Dir_t far *dirp, far *p, far *q;
  249.  
  250.     if (inode > NUMINODES || (dirp = InodeTable[inode]) == (Dir_t far *) NULL)
  251.       return FALSE;
  252.  
  253.     if (dirp->subdir != (Dir_t far *) NULL)
  254.       return FALSE;
  255.  
  256.     /* If this is the first node in the list, simply point the parent   */
  257.     /* to the next item.                        */
  258.     if (dirp->parent->subdir->inode == (u_short) inode) {
  259.     dirp->parent->subdir = dirp->next;
  260.     }
  261.     else {
  262.     /* Scan the list looking for inode */
  263.     p = dirp->parent->subdir->next;  q = dirp->parent->subdir;
  264.     while(p != (Dir_t far *) NULL && p->inode != (u_short) inode) {
  265.         q = p; p = p->next;
  266.     }
  267.     /* Unlink this node from the list */
  268.     if (p == (Dir_t far *) NULL)
  269.         return FALSE;
  270.     q->next = p->next;
  271.     }
  272.  
  273.     /* Free up the memory used by this inode and its attributes */
  274.     if (dirp->attr != (Acache_t far *) NULL) {
  275.     dirp->attr->prev->next = dirp->attr->next;
  276.     dirp->attr->next->prev = dirp->attr->prev;
  277.     dirp->attr->next = attrfree;
  278.     attrfree = dirp->attr;
  279.     }
  280.     (void) _ffree (dirp);
  281.     return TRUE;
  282. }
  283.  
  284. /*
  285.  *  Dir_t far *findindirlist(name, Dir_t far *parent, Dir_t far **dirlist) --
  286.  *      Finds the node with name in dirlist and returns a ptr to it, or makes
  287.  *      a new node if none is found, and returns a pointer to the new node.
  288.  */
  289. Dir_t far *findindirlist(name, parent, dirlist)
  290.     char *name;
  291.     Dir_t far *parent;
  292.     Dir_t far * far *dirlist;
  293. {
  294.     int lexico;        /* lexicographic comparator */
  295.     Dir_t far *new;
  296.     Dir_t far *p;
  297.     Dir_t far *q;        /* for inserting down the list */
  298.     char str[MAXFILENAMELEN];
  299.  
  300.     if (*dirlist == (Dir_t far *) NULL) {          /* NULL entry */
  301.     *dirlist = makenewdirnode(name, parent);
  302.  
  303.     return *dirlist;
  304.     }
  305.  
  306.     bcopy_fn((*dirlist)->name, str, MAXFILENAMELEN);
  307.     if ((lexico = strcmp(name, str)) < 0) {
  308.     Dir_t far *tmp;
  309.  
  310.     /* must insert in front */
  311.  
  312.     new = makenewdirnode(name, parent);
  313.     tmp = *dirlist;
  314.     *dirlist = new;
  315.     new->next = tmp;
  316.  
  317.     return new;
  318.     }
  319.     else if (lexico == 0)             /* found the node */
  320.       return *dirlist;
  321.  
  322.     /* cdr down the list and find node or find place to insert */
  323.     p = (*dirlist)->next;  q = *dirlist;
  324.     while(p != (Dir_t far *) NULL) {
  325.     bcopy_fn((p)->name, str, MAXFILENAMELEN);
  326.     if ((lexico = strcmp(name, str)) == 0)
  327.       return p;        /* found it */
  328.     else if (lexico < 0)
  329.       break;            /* should insert here */
  330.     q = p; p = p->next;        /* go on to next elt */
  331.     }
  332.     /* this is where we insert */
  333.     new = makenewdirnode(name, parent);
  334.     q->next = new;
  335.     new->next = p;
  336.  
  337.     return new;
  338. }
  339.  
  340. /*
  341.  *  u_long insertapath(char *path, Dir_t far *parent, Dir_t far **dirlist) 
  342.  *      Inserts path into dirlist and returns final inode number.
  343.  */
  344. static u_long insertapath(path, parent, dirlist)
  345.      char *path;
  346.      Dir_t far *parent;
  347.      Dir_t far * far *dirlist;
  348. {
  349.     char comp[MAXFILENAMELEN];        /* 11 is max length of one component */
  350.     Dir_t far *compnode;    /* the component node */
  351.  
  352.     getcomp(comp, &path);                /* get component */
  353.     compnode = findindirlist(comp, parent, (Dir_t far * far *) dirlist);
  354.     if (*path == '\0') {
  355.     return (u_long) compnode->inode;    /* no more descents needed */
  356.     } else
  357.       return insertapath(path, compnode, (Dir_t far * far *) &
  358.              (compnode->subdir));
  359. }
  360.  
  361. /*
  362.  *  u_long addpathtodirtree(char *path) --
  363.  *      Adds a path to the directory tree and return it's inode number.
  364.  */
  365. u_long addpathtodirtree(path)
  366.     char *path;
  367. {
  368.     u_long inode;
  369.  
  370.     if (inodefp == (FILE *) NULL)
  371.       inodefp = fopen(INODEFILE, "a");
  372.     (void) fprintf(inodefp, "%s\n", path);    /* add to inode file */
  373.     return insertapath(path, (Dir_t far *) NULL, (Dir_t far * far *) &RootDir);
  374.  
  375.     return inode;
  376. }
  377.  
  378. /*
  379.  *  u_long ingetentry (u_long inode, u_long offset, char *name) --
  380.  *      Finds the node at a given offset in dirlist and returns
  381.  *    its name.  Returns -1 if the node is invalid or the offset
  382.  *    is too large.
  383.  */
  384. u_long ingetentry (inode, offset, name)
  385.      u_long inode;
  386.      u_long offset;
  387.      char   *name;
  388. {
  389.     Dir_t far *p, far *q;        /* for scanning the list */
  390. u_long x = offset;
  391.  
  392.     if (inode > NUMINODES || InodeTable[inode] == (Dir_t far *) NULL)
  393.       return -1;
  394.  
  395.     /* Handle first two entries specially. */
  396.     if (offset == 0) {
  397.     strcpy (name, ".");
  398.     return inode;
  399.     }
  400.     else if (offset == 1) {
  401.     strcpy (name, "..");
  402.     return InodeTable[inode]->top ? inode :
  403.       InodeTable[inode]->parent->inode;
  404.     }
  405.     offset -= 2;
  406.  
  407.     if ((q = InodeTable[inode]->subdir) == NULL)
  408.       return -1;
  409.     p = q->next;
  410.  
  411.     /* cdr down the list */
  412.     while (offset--) {
  413.     if (p != (Dir_t far *) NULL) {
  414.         q = p; p = p->next;        /* go on to next elt */
  415.     }
  416.     else
  417.       return -1;
  418.     }
  419.     bcopy_fn (q->name, name, MAXFILENAMELEN);
  420. /*    DBGPRT3 (inode, "%ld offs %ld %s", inode, x, name); */
  421.     return (u_long) q->inode;
  422. }
  423.  
  424. #if INODE_DEBUG
  425. /*
  426.  *  void shownode(Dir_t far *dirt) --
  427.  *      Debugging aid.  Dumps the node.
  428.  */
  429. static void shownode(dirt)
  430.     Dir_t far *dirt;
  431. {
  432.     (void) printf("Name: %s;\t Inode #: %d\n", dirt->name, dirt->inode);
  433. }
  434.  
  435. /*
  436.  *  void showtree(Dir_t far *dirt) --
  437.  *      Debugging aid.  Dumps the tree.
  438.  */
  439. void showtree(dirt)
  440.     Dir_t far *dirt;
  441. {
  442.     while(dirt != (Dir_t far *) NULL) {
  443.     shownode(dirt);
  444.     if (dirt->subdir != (Dir_t far *) NULL) {
  445.         (void) printf("And in this directory... \n");
  446.         showtree(dirt->subdir);
  447.     }
  448.     dirt = dirt->next;
  449.     }
  450. }
  451. #endif /* INODE_DEBUG */
  452.  
  453. /*
  454.  *  u_long pntoin(char *path) --
  455.  *      Returns inode number corresponding to path.  Path should already
  456.  *      exist.  Returns -1 for error.
  457.  */
  458. #define isdot(path, len) (*((path) + (len) -1) == '.')
  459. #define isdotdot(path, len) (isdot(path,len) && (*((path) + (len) - 2)) == '.')
  460. u_long pntoin(path)
  461.     char *path;
  462. {
  463.     char comp[MAXFILENAMELEN];        /* component of filename */
  464.     Dir_t far *p;
  465.     int len;
  466.     char str[MAXFILENAMELEN];
  467.  
  468.     len = strlen(path);
  469.     if (isdotdot(path, len))
  470.       *(path + len -3) = '\0';
  471.     else if (isdot(path, len))
  472.       *(path + len -2) = '\0';
  473.     
  474.     p = RootDir;            /* start search from root */
  475.     while(p != (Dir_t far *) NULL) {        /* search down the tree */
  476.     int lex;
  477.  
  478.     getcomp(comp, &path);        /* search across the tree */
  479.     while(p != (Dir_t far *) NULL) {
  480.         bcopy_fn((p)->name, str, MAXFILENAMELEN);
  481.         if ((lex = strcmp(comp, str)) == 0)
  482.           break;
  483.         else if (lex < 0)    /* overshot - not found */
  484.           return -1;
  485.         p = p->next;    /* across on this level */
  486.     }
  487.     if (p == (Dir_t far *) NULL)
  488.       return -1;
  489.     else if (*path == '\0') 
  490.       return (u_long) p->inode;
  491.     else
  492.       p = p->subdir;        /* down one level */
  493.     }
  494.     return -1;
  495. }
  496.  
  497. /*
  498.  *  char *intopn(u_long inode, char *path) --
  499.  *      Converts inode to path name in dos format.  DOS style path name
  500.  *    is returned.  A NULL is returned if there is no such inode.
  501.  */
  502. char *intopn(inode, path)
  503.      u_long inode;
  504.      char *path;
  505. {
  506.     Dir_t far *dirp;
  507.     char  *ptr;
  508.     u_short stack[30];    /* room for 30 nested directories */
  509.     u_short *stackptr;
  510.  
  511.     if ((dirp = InodeTable[inode]) == (Dir_t far *) NULL)
  512.       return NULL;
  513.  
  514.     /* move upwards and set parents to point to this child */
  515.     stackptr = stack;
  516.     while(dirp->parent != (Dir_t far *) NULL) {
  517.     *stackptr++ = dirp->inode;
  518.     dirp = dirp->parent;        /* go to parent */
  519.     }
  520.     /* first get the drive name set up in path */
  521.     bcopy_fn((dirp->name), path, MAXFILENAMELEN);
  522.     ptr = path+1;
  523.     *ptr++ = ':';
  524.  
  525.     while (--stackptr >= stack) {
  526.     *ptr++ = '\\';
  527.     bcopy_fn(InodeTable[*stackptr]->name, ptr, MAXFILENAMELEN);
  528.     while (*ptr) ptr++;
  529.     }
  530.     *ptr++ = '\0';
  531.     return path;
  532. }
  533.  
  534. /*
  535.  *  char *intoname(u_long inode) --
  536.  *      Converts inode to name of file.
  537.  */
  538. char *intoname(inode)
  539.     u_long inode;
  540. {
  541. static char temname[MAXFILENAMELEN];
  542.  
  543.     if (inode > NUMINODES)
  544.         return NULL;
  545.     bcopy_fn((InodeTable[inode])->name, temname, MAXFILENAMELEN);
  546.     return temname;
  547. }    
  548.  
  549. /*
  550.  *  u_long parentinode(u_long inode)
  551.  *      Returns inode number of parent.
  552.  */
  553. u_long parentinode(inode)
  554.      u_long inode;
  555. {
  556.     Dir_t far *parent;
  557.     Dir_t far *dirp;
  558.  
  559.     if (inode < NUMINODES && (dirp = InodeTable[inode])!=(Dir_t far *) NULL) {
  560.     if (dirp->top)
  561.       return inode;
  562.     else if    ((parent = dirp->parent) != (Dir_t far *) NULL)
  563.       return (u_long) parent->inode;
  564.     }
  565.     return 0;
  566. }
  567.  
  568. /*
  569.  * inattrset (u_long inode, struct nfsfattr *)
  570.  *    Saves file attributes for a given inode.
  571.  */
  572. struct nfsfattr *inattrset (inode, attr)
  573.      u_long inode;
  574.      struct nfsfattr *attr;
  575. {
  576.     Dir_t far *dirp;
  577.  
  578.     if (inode > NUMINODES)
  579.       return (struct nfsfattr *) NULL;
  580.     if ((dirp = InodeTable[inode]) != (Dir_t far *) NULL) {
  581.     if (dirp->attr == (Acache_t far *) NULL) {
  582.  
  583.         /* Allocate an attributes entry */
  584.         dirp->attr = attrfree;
  585.         if (dirp->attr == (struct nfsfattr far *) NULL) {
  586.  
  587.         /* List is full:  unlink the tail entry from its */
  588.         /* previously associated inode.             */
  589.         dirp->attr = attrcache->prev;
  590.         InodeTable[dirp->attr->inode]->attr = NULL;
  591.         dirp->attr->prev->next = attrcache;
  592.         attrcache->prev = dirp->attr->prev;
  593.         }
  594.         else {
  595.         /* Unlink the entry from the free list.        */
  596.         attrfree = attrfree->next;
  597.         }
  598.  
  599.         /* Add the entry to the head of the active list.    */
  600.         dirp->attr->next = attrcache->next;
  601.         dirp->attr->prev = attrcache;
  602.         attrcache->next->prev = dirp->attr;
  603.         attrcache->next = dirp->attr;
  604.     }
  605.     dirp->attr->inode = (u_short) inode;
  606.     (void) bcopy_nf(attr, &dirp->attr->fattr, sizeof (struct nfsfattr));
  607.     }
  608.     else
  609.       return (struct nfsfattr *) NULL;
  610. }
  611.  
  612. /*
  613.  * inattrget (u_long inode, struct nfsfattr *)
  614.  *    Fetches the attributes previously saved within a given inode.
  615.  */
  616. struct nfsfattr *inattrget (inode, attr)
  617.      u_long inode;
  618.      struct nfsfattr *attr;
  619. {
  620.     Dir_t far *dirp;
  621.  
  622.     if (inode > NUMINODES)
  623.       return (struct nfsfattr *) NULL;
  624.     if ((dirp = InodeTable[inode]) != (Dir_t far *) NULL) {
  625.     if (dirp->attr == (Acache_t far *) NULL)
  626.         return (struct nfsfattr *) NULL;
  627.     (void) bcopy_fn(&dirp->attr->fattr, attr, sizeof (struct nfsfattr));
  628.  
  629.     /* Move entry to head of attributes cache */
  630.     if (dirp->attr != attrcache->next) {
  631.         dirp->attr->prev->next = dirp->attr->next;
  632.         dirp->attr->next->prev = dirp->attr->prev;
  633.         dirp->attr->next = attrcache->next;
  634.         attrcache->next->prev = dirp->attr;
  635.         attrcache->next = dirp->attr;
  636.         dirp->attr->prev = attrcache;
  637.     }
  638.     return (attr);
  639.     }
  640.     else
  641.       return (struct nfsfattr *) NULL;
  642. }
  643.  
  644. /*
  645.  * ingetfsid (u_long inode)
  646.  *    Fetches the filesystem ID (drive number) of an inode.
  647.  *    Returns -1 if inode is undefined.
  648.  */
  649. int ingetfsid (inode)
  650.      u_long inode;
  651. {
  652.     Dir_t far *dirp;
  653.  
  654.     if (inode > NUMINODES || (dirp = InodeTable[inode]) == (Dir_t far *) NULL)
  655.       return -1;
  656.     return dirp->fsid;
  657. }
  658.  
  659. /*
  660.  *  u_long newinodeno() --
  661.  *    Returns a new inode number, or aborts if we run out of inodes.
  662.  *    A system cleanup must then occur.
  663.  */
  664. static u_long newinodeno()
  665. {
  666.     if (lastinodeno > NUMINODES) {
  667.     DBGPRT0 (nfserr, "ran out of inodes");
  668.     (void) fprintf(stderr, "server err: out of inodes\n");
  669.     abort();
  670.     }
  671.     return lastinodeno++;
  672. }
  673.  
  674.  
  675. /*
  676.  *  fhandle_t pntofh(char *path) --
  677.  *      Converts path name to file handle.  DOS or UNIX style paths.
  678.  */
  679. fhandle_t pntofh(path)
  680.     char *path;
  681. {
  682.     u_long inodeno;
  683.     fhandle_t fh;
  684.     Dir_t far *dirp;
  685.  
  686.     (void) bzero(&fh, sizeof(fhandle_t));
  687.     if ((inodeno = pntoin(path)) == -1)
  688.       inodeno = addpathtodirtree(path);
  689.     dirp = InodeTable[inodeno];
  690.     fh.f.fh_fno = inodeno;
  691.     fh.p.fh_fno = (dirp->top ? inodeno : dirp->parent->inode);
  692.     fh.f.fh_fsid = fh.p.fh_fsid = (dev_t) dirp->fsid;
  693.     fh.f.fh_fgen = (time_t) dirp->gen;
  694.     (void) bcopy_fn(dirp->name, fh.fh_pn, MAXFILENAMELEN);
  695.     
  696.     return fh;
  697. }
  698.  
  699. /*
  700.  * bool_t checkfh (fhandle_t *fhp) --
  701.  *    Checks whether the given fhandle is still valid    (it may not
  702.  *      be if the inode number has been recycled).
  703.  */
  704. bool_t checkfh (fhp)
  705. fhandle_t *fhp;
  706. {
  707.     u_long inode;
  708.     Dir_t far *dirp;
  709.  
  710.     inode = fhp->f.fh_fno;
  711.     if (inode > NUMINODES || (dirp = InodeTable[inode]) == NULL)
  712.       return FALSE;
  713.     if (fhp->p.fh_fno != (dirp->top ? inode : dirp->parent->inode) ||
  714.     dirp->fsid != (u_char) fhp->f.fh_fsid ||
  715.     dirp->gen != (u_short) fhp->f.fh_fgen) {
  716.     DBGPRT3 (nfserr, "checkfh:  node %ld gen %d/%d", inode,
  717.          (int) fhp->f.fh_fgen, dirp->gen);
  718.       return FALSE;
  719.     }
  720.     else
  721.       return TRUE;
  722. }
  723.  
  724. #ifdef INODE_DEBUG
  725. main()
  726. {
  727.     char *s, path[MAXPATHNAMELEN];
  728.  
  729.     addpathtodirtree("/c/bin/test");
  730.     addpathtodirtree("/d/stan/src/unfsd");
  731.     addpathtodirtree("/c/bin/testee");
  732.     addpathtodirtree("/d/stan/src/unfsd");
  733.     addpathtodirtree("/d/stan/src/unfsd/tester");
  734.     showtree(RootDir);
  735.     (void) printf("pntoin /d/stan/src is %ld\n", pntoin("/d/stan/src"));
  736.     s = intopn(7, path);
  737.     (void) printf("intopn 7 : %s\n", s);
  738.     (void) free(s);
  739.     s = intopn(7, path);
  740.     (void) printf("intopn 7 : %s\n", s);
  741. }
  742. #endif
  743.