home *** CD-ROM | disk | FTP | other *** search
/ Borland Programmer's Resource / Borland_Programmers_Resource_CD_1995.iso / utils / sossntr3 / src / inodes.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-19  |  19.2 KB  |  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 64000
  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 *next;
  45.     struct _acache *prev;
  46.     u_short             inode;
  47.     struct nfsfattr     fattr;
  48. } Acache_t;
  49.  
  50. static Acache_t *attrcache;     /* Head and tail pointers */
  51. static Acache_t *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 *next;   /* next file in same directory */
  61.     struct DIRNODE *subdir; /* ptr to subdirectory entries */
  62.     struct DIRNODE *parent; /* ptr to parent directory */
  63.     Acache_t *attr;     /* file attributes, if known */
  64. } Dir_t;
  65.  
  66.   /* the directory structure begins here */
  67. static Dir_t *RootDir = NULL;
  68.  
  69.   /* the inode table - list of directory node pointers  */
  70.   /* allocated on initialization            */
  71. typedef Dir_t *Inode_t;
  72.  
  73. Inode_t *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 *) malloc (NUMINODES * 4)) == NULL)
  92.       return FALSE;
  93.  
  94.     /* Initialize attributes cache */
  95.  
  96.     if ((attrcache = (Acache_t *) malloc (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 = 0;
  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 *) NULL,
  128.                  (Dir_t **) &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 *) NULL,
  143.                  (Dir_t **) &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 *parent) --
  193.  *      Returns new directory node initialized with name.
  194.  */
  195. Dir_t *makenewdirnode(name, parent)
  196.      char *name;
  197.      Dir_t *parent;
  198. {
  199.     Dir_t *new;
  200.  
  201.     new = (Dir_t *) malloc(sizeof(Dir_t));
  202.     if (new == (Dir_t *) 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 *) NULL;
  210.     new->attr = NULL;
  211.     new->top  = FALSE;
  212.     new->gen  = gencount++;
  213.     if (parent == (Dir_t *) 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.     if (_inremnode (inode)) {
  229.     if (inodefp == (FILE *) NULL)
  230.       inodefp = fopen(INODEFILE, "a");
  231.     (void) fprintf(inodefp, "-%ld\n", inode);   /* add to inode file */
  232.     }
  233. /*   else {
  234.  *  DBGPRT1 (nfserr, "inremnode %ld failed", inode);
  235.  *  }
  236.  */
  237. }
  238.  
  239. /*
  240.  *  bool_t _inremnode(u_long inode) --
  241.  *      Prunes an inode from the tree.
  242.  */
  243. static bool_t _inremnode (inode)
  244.      u_long inode;
  245. {
  246.     Dir_t *dirp, *p, *q;
  247.  
  248.     if (inode > NUMINODES || (dirp = InodeTable[inode]) == (Dir_t *) NULL)
  249.       return FALSE;
  250.  
  251.     if (dirp->subdir != (Dir_t *) NULL)
  252.       return FALSE;
  253.  
  254.     /* If this is the first node in the list, simply point the parent   */
  255.     /* to the next item.                        */
  256.     if (dirp->parent->subdir->inode == (u_short) inode) {
  257.     dirp->parent->subdir = dirp->next;
  258.     }
  259.     else {
  260.     /* Scan the list looking for inode */
  261.     p = dirp->parent->subdir->next;  q = dirp->parent->subdir;
  262.     while(p != (Dir_t *) NULL && p->inode != (u_short) inode) {
  263.         q = p; p = p->next;
  264.     }
  265.     /* Unlink this node from the list */
  266.     if (p == (Dir_t *) NULL)
  267.         return FALSE;
  268.     q->next = p->next;
  269.     }
  270.  
  271.     /* Free up the memory used by this inode and its attributes */
  272.     if (dirp->attr != (Acache_t *) NULL) {
  273.     dirp->attr->prev->next = dirp->attr->next;
  274.     dirp->attr->next->prev = dirp->attr->prev;
  275.     dirp->attr->next = attrfree;
  276.     attrfree = dirp->attr;
  277.     }
  278.     (void) free (dirp);
  279.     InodeTable[inode] = NULL;  //Fix from Nthaniel Mishkin
  280.     return TRUE;
  281. }
  282.  
  283. /*
  284.  *  Dir_t *findindirlist(name, Dir_t *parent, Dir_t **dirlist) --
  285.  *      Finds the node with name in dirlist and returns a ptr to it, or makes
  286.  *      a new node if none is found, and returns a pointer to the new node.
  287.  */
  288. Dir_t *findindirlist(name, parent, dirlist)
  289.     char *name;
  290.     Dir_t *parent;
  291.     Dir_t **dirlist;
  292. {
  293.     int lexico;     /* lexicographic comparator */
  294.     Dir_t *new;
  295.     Dir_t *p;
  296.     Dir_t *q;       /* for inserting down the list */
  297.     char str[MAXFILENAMELEN];
  298.  
  299.     if (*dirlist == (Dir_t *) NULL) {         /* NULL entry */
  300.     *dirlist = makenewdirnode(name, parent);
  301.  
  302.     return *dirlist;
  303.     }
  304.  
  305.     bcopy_fn((*dirlist)->name, str, MAXFILENAMELEN);
  306.     if ((lexico = stricmp(name, str)) < 0) {
  307.     Dir_t *tmp;
  308.  
  309.     /* must insert in front */
  310.  
  311.     new = makenewdirnode(name, parent);
  312.     tmp = *dirlist;
  313.     *dirlist = new;
  314.     new->next = tmp;
  315.  
  316.     return new;
  317.     }
  318.     else if (lexico == 0)           /* found the node */
  319.       return *dirlist;
  320.  
  321.     /* cdr down the list and find node or find place to insert */
  322.     p = (*dirlist)->next;  q = *dirlist;
  323.     while(p != (Dir_t *) NULL) {
  324.     bcopy_fn((p)->name, str, MAXFILENAMELEN);
  325.     if ((lexico = stricmp(name, str)) == 0)
  326.       return p;     /* found it */
  327.     else if (lexico < 0)
  328.       break;            /* should insert here */
  329.     q = p; p = p->next;     /* go on to next elt */
  330.     }
  331.     /* this is where we insert */
  332.     new = makenewdirnode(name, parent);
  333.     q->next = new;
  334.     new->next = p;
  335.  
  336.     return new;
  337. }
  338.  
  339. /*
  340.  *  u_long insertapath(char *path, Dir_t *parent, Dir_t **dirlist) 
  341.  *      Inserts path into dirlist and returns final inode number.
  342.  */
  343. static u_long insertapath(path, parent, dirlist)
  344.      char *path;
  345.      Dir_t *parent;
  346.      Dir_t **dirlist;
  347. {
  348.     char comp[MAXFILENAMELEN];      /* 11 is max length of one component */
  349.     Dir_t *compnode;    /* the component node */
  350.  
  351.     getcomp(comp, &path);               /* get component */
  352.     compnode = findindirlist(comp, parent, (Dir_t **) dirlist);
  353.     if (*path == '\0') {
  354.     return (u_long) compnode->inode;    /* no more descents needed */
  355.     } else
  356.       return insertapath(path, compnode, (Dir_t **) &
  357.              (compnode->subdir));
  358. }
  359.  
  360. /*
  361.  *  u_long addpathtodirtree(char *path) --
  362.  *      Adds a path to the directory tree and return it's inode number.
  363.  */
  364. u_long addpathtodirtree(path)
  365.     char *path;
  366. {
  367.     u_long inode;
  368.  
  369.     if (inodefp == (FILE *) NULL)
  370.       inodefp = fopen(INODEFILE, "a");
  371.     (void) fprintf(inodefp, "%s\n", path);  /* add to inode file */
  372.     return insertapath(path, (Dir_t *) NULL, (Dir_t **) &RootDir);
  373.  
  374.     return inode;
  375. }
  376.  
  377. /*
  378.  *  u_long ingetentry (u_long inode, u_long offset, char *name) --
  379.  *      Finds the node at a given offset in dirlist and returns
  380.  *  its name.  Returns -1 if the node is invalid or the offset
  381.  *  is too large.
  382.  */
  383. long ingetentry (inode, offset, name)
  384.      u_long inode;
  385.      u_long offset;
  386.      char   *name;
  387. {
  388.     Dir_t *p, *q;       /* for scanning the list */
  389. u_long x = offset;
  390.  
  391.     if (inode > NUMINODES || InodeTable[inode] == (Dir_t *) NULL)
  392.       return -1;
  393.  
  394.     /* Handle first two entries specially. */
  395.     if (offset == 0) {
  396.     strcpy (name, ".");
  397.     return inode;
  398.     }
  399.     else if (offset == 1) {
  400.     strcpy (name, "..");
  401.     return InodeTable[inode]->top ? inode :
  402.       InodeTable[inode]->parent->inode;
  403.     }
  404.     offset -= 2;
  405.  
  406.     if ((q = InodeTable[inode]->subdir) == NULL)
  407.       return -1;
  408.     p = q->next;
  409.  
  410.     /* cdr down the list */
  411.     while (offset--) {
  412.     if (p != (Dir_t *) NULL) {
  413.         q = p; p = p->next;     /* go on to next elt */
  414.     }
  415.     else
  416.       return -1;
  417.     }
  418.     bcopy_fn (q->name, name, MAXFILENAMELEN);
  419. /*    DBGPRT3 (inode, "%ld offs %ld %s", inode, x, name); */
  420.     return (u_long) q->inode;
  421. }
  422.  
  423. #if INODE_DEBUG
  424. /*
  425.  *  void shownode(Dir_t *dirt) --
  426.  *      Debugging aid.  Dumps the node.
  427.  */
  428. static void shownode(dirt)
  429.     Dir_t *dirt;
  430. {
  431.     (void) printf("Name: %s;\t Inode #: %d\n", dirt->name, dirt->inode);
  432. }
  433.  
  434. /*
  435.  *  void showtree(Dir_t *dirt) --
  436.  *      Debugging aid.  Dumps the tree.
  437.  */
  438. void showtree(dirt)
  439.     Dir_t *dirt;
  440. {
  441.     while(dirt != (Dir_t *) NULL) {
  442.     shownode(dirt);
  443.     if (dirt->subdir != (Dir_t *) NULL) {
  444.         (void) printf("And in this directory... \n");
  445.         showtree(dirt->subdir);
  446.     }
  447.     dirt = dirt->next;
  448.     }
  449. }
  450. #endif /* INODE_DEBUG */
  451.  
  452. /*
  453.  *  u_long pntoin(char *path) --
  454.  *      Returns inode number corresponding to path.  Path should already
  455.  *      exist.  Returns -1 for error.
  456.  */
  457. #define isdot(path, len) (*((path) + (len) -1) == '.')
  458. #define isdotdot(path, len) (isdot(path,len) && (*((path) + (len) - 2)) == '.')
  459. long pntoin(path)
  460.     char *path;
  461. {
  462.     char comp[MAXFILENAMELEN];      /* component of filename */
  463.     Dir_t *p;
  464.     int len;
  465.     char str[MAXFILENAMELEN];
  466.  
  467.     len = strlen(path);
  468.     if (isdotdot(path, len))
  469.       *(path + len -3) = '\0';
  470.     else if (isdot(path, len))
  471.       *(path + len -2) = '\0';
  472.     
  473.     p = RootDir;            /* start search from root */
  474.     while(p != (Dir_t *) NULL) {        /* search down the tree */
  475.     int lex;
  476.  
  477.     getcomp(comp, &path);       /* search across the tree */
  478.     while(p != (Dir_t *) NULL) {
  479.         bcopy_fn((p)->name, str, MAXFILENAMELEN);
  480.         if ((lex = stricmp(comp, str)) == 0)
  481.           break;
  482.         else if (lex < 0)   /* overshot - not found */
  483.           return -1;
  484.         p = p->next;    /* across on this level */
  485.     }
  486.     if (p == (Dir_t *) NULL)
  487.       return -1;
  488.     else if (*path == '\0') 
  489.       return (u_long) p->inode;
  490.     else
  491.       p = p->subdir;        /* down one level */
  492.     }
  493.     return -1;
  494. }
  495.  
  496. /*
  497.  *  char *intopn(u_long inode, char *path) --
  498.  *      Converts inode to path name in dos format.  DOS style path name
  499.  *  is returned.  A NULL is returned if there is no such inode.
  500.  */
  501. char *intopn(inode, path)
  502.      u_long inode;
  503.      char *path;
  504. {
  505.     Dir_t *dirp;
  506.     char  *ptr;
  507.     u_short stack[30];  /* room for 30 nested directories */
  508.     u_short *stackptr;
  509.  
  510.     if ((dirp = InodeTable[inode]) == (Dir_t *) NULL)
  511.       return NULL;
  512.  
  513.     /* move upwards and set parents to point to this child */
  514.     stackptr = stack;
  515.     while(dirp->parent != (Dir_t *) NULL) {
  516.     *stackptr++ = dirp->inode;
  517.     dirp = dirp->parent;        /* go to parent */
  518.     }
  519.     /* first get the drive name set up in path */
  520.     bcopy_fn((dirp->name), path, MAXFILENAMELEN);
  521.     ptr = path+1;
  522.     *ptr++ = ':';
  523.  
  524.     while (--stackptr >= stack) {
  525.     *ptr++ = '\\';
  526.     bcopy_fn(InodeTable[*stackptr]->name, ptr, MAXFILENAMELEN);
  527.     while (*ptr) ptr++;
  528.     }
  529.     *ptr++ = '\0';
  530.     return path;
  531. }
  532.  
  533. /*
  534.  *  char *intoname(u_long inode) --
  535.  *      Converts inode to name of file.
  536.  */
  537. char *intoname(inode)
  538.     u_long inode;
  539. {
  540. static char temname[MAXFILENAMELEN];
  541.  
  542.     if (inode > NUMINODES)
  543.         return NULL;
  544.     bcopy_fn((InodeTable[inode])->name, temname, MAXFILENAMELEN);
  545.     return temname;
  546. }   
  547.  
  548. /*
  549.  *  u_long parentinode(u_long inode)
  550.  *      Returns inode number of parent.
  551.  */
  552. u_long parentinode(inode)
  553.      u_long inode;
  554. {
  555.     Dir_t *parent;
  556.     Dir_t *dirp;
  557.  
  558.     if (inode < NUMINODES && (dirp = InodeTable[inode])!=(Dir_t *) NULL) {
  559.     if (dirp->top)
  560.       return inode;
  561.     else if ((parent = dirp->parent) != (Dir_t *) NULL)
  562.       return (u_long) parent->inode;
  563.     }
  564.     return 0;
  565. }
  566.  
  567. /*
  568.  * inattrset (u_long inode, struct nfsfattr *)
  569.  *    Saves file attributes for a given inode.
  570.  */
  571. struct nfsfattr *inattrset (inode, attr)
  572.      u_long inode;
  573.      struct nfsfattr *attr;
  574. {
  575.     Dir_t *dirp;
  576.  
  577.     if (inode > NUMINODES)
  578.       return (struct nfsfattr *) NULL;
  579.     if ((dirp = InodeTable[inode]) != (Dir_t *) NULL) {
  580.     if (dirp->attr == (Acache_t *) NULL) {
  581.  
  582.         /* Allocate an attributes entry */
  583.         dirp->attr = attrfree;
  584.         if (dirp->attr == NULL) {
  585.  
  586.         /* List is full:  unlink the tail entry from its */
  587.         /* previously associated inode.          */
  588.         dirp->attr = attrcache->prev;
  589.         InodeTable[dirp->attr->inode]->attr = NULL;
  590.         dirp->attr->prev->next = attrcache;
  591.         attrcache->prev = dirp->attr->prev;
  592.         }
  593.         else {
  594.         /* Unlink the entry from the free list.     */
  595.         attrfree = attrfree->next;
  596.         }
  597.  
  598.         /* Add the entry to the head of the active list.    */
  599.         dirp->attr->next = attrcache->next;
  600.         dirp->attr->prev = attrcache;
  601.         attrcache->next->prev = dirp->attr;
  602.         attrcache->next = dirp->attr;
  603.     }
  604.     dirp->attr->inode = (u_short) inode;
  605.     (void) bcopy_nf((char*)attr, (char*)(&dirp->attr->fattr), sizeof (struct nfsfattr));
  606.     }
  607.     else
  608.       return (struct nfsfattr *) NULL;
  609. }
  610.  
  611. /*
  612.  * inattrget (u_long inode, struct nfsfattr *)
  613.  *    Fetches the attributes previously saved within a given inode.
  614.  */
  615. struct nfsfattr *inattrget (inode, attr)
  616.      u_long inode;
  617.      struct nfsfattr *attr;
  618. {
  619.     Dir_t *dirp;
  620.  
  621.     if (inode > NUMINODES)
  622.       return (struct nfsfattr *) NULL;
  623.     if ((dirp = InodeTable[inode]) != (Dir_t *) NULL) {
  624.     if (dirp->attr == (Acache_t *) NULL)
  625.         return (struct nfsfattr *) NULL;
  626.     (void) bcopy_fn((char*)(&dirp->attr->fattr), (char*)attr, sizeof (struct nfsfattr));
  627.  
  628.     /* Move entry to head of attributes cache */
  629.     if (dirp->attr != attrcache->next) {
  630.         dirp->attr->prev->next = dirp->attr->next;
  631.         dirp->attr->next->prev = dirp->attr->prev;
  632.         dirp->attr->next = attrcache->next;
  633.         attrcache->next->prev = dirp->attr;
  634.         attrcache->next = dirp->attr;
  635.         dirp->attr->prev = attrcache;
  636.     }
  637.     return (attr);
  638.     }
  639.     else
  640.       return (struct nfsfattr *) NULL;
  641. }
  642.  
  643. /*
  644.  * ingetfsid (u_long inode)
  645.  *    Fetches the filesystem ID (drive number) of an inode.
  646.  *    Returns -1 if inode is undefined.
  647.  */
  648. int ingetfsid (inode)
  649.      u_long inode;
  650. {
  651.     Dir_t *dirp;
  652.  
  653.     if (inode > NUMINODES || (dirp = InodeTable[inode]) == (Dir_t *) NULL)
  654.       return -1;
  655.     return dirp->fsid;
  656. }
  657.  
  658. /*
  659.  *  u_long newinodeno() --
  660.  *  Returns a new inode number, or aborts if we run out of inodes.
  661.  *  A system cleanup must then occur.
  662.  */
  663. static u_long newinodeno()
  664. {
  665.     if (lastinodeno > NUMINODES) {
  666.     DBGPRT0 (nfserr, "ran out of inodes");
  667.     (void) fprintf(stderr, "server err: out of inodes\n");
  668.     abort();
  669.     }
  670.     return lastinodeno++;
  671. }
  672.  
  673.  
  674. /*
  675.  *  fhandle_t pntofh(char *path) --
  676.  *      Converts path name to file handle.  DOS or UNIX style paths.
  677.  */
  678. fhandle_t pntofh(path)
  679.     char *path;
  680. {
  681.     u_long inodeno;
  682.     fhandle_t fh;
  683.     Dir_t *dirp;
  684.  
  685.     (void) bzero((char*)&fh, sizeof(fhandle_t));
  686.     if ((inodeno = pntoin(path)) == -1)
  687.       inodeno = addpathtodirtree(path);
  688.     dirp = InodeTable[inodeno];
  689.     fh.f.fh_fno = inodeno;
  690.     fh.p.fh_fno = (dirp->top ? inodeno : dirp->parent->inode);
  691.     fh.f.fh_fsid = fh.p.fh_fsid = (dev_t) dirp->fsid;
  692.     fh.f.fh_fgen = (time_t) dirp->gen;
  693.     //(void) bcopy_fn(dirp->name, fh.fh_pn, MAXFILENAMELEN);
  694.     (void) bcopy_fn(dirp->name, fh.fh_pn, FH_PN);
  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 *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.