home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD2.mdf / gnu / djgpp / libsrc / c / sys / stat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-08-24  |  3.4 KB  |  144 lines

  1. /*
  2.   (c) Copyright 1992 Eric Backus
  3.  
  4.   This software may be used freely so long as this copyright notice is
  5.   left intact.  There is no warrantee on this software.
  6. */
  7.  
  8. #include <sys/stat.h>
  9. #include <string.h>
  10. #include <stdlib.h>
  11.  
  12. #include <dos.h>
  13. #include <errno.h>
  14. #include <stdio.h>
  15.  
  16. extern int    stat_assist(const char *, struct stat *);
  17. extern void    _fixpath(const char *, char *);
  18.  
  19. struct path_list
  20. {
  21.     struct path_list    *next;
  22.     char        *path;
  23.     int            inode;
  24. };
  25.  
  26. static int
  27. fixinode(const char *path, struct stat *buf)
  28. {
  29.     static struct path_list    *path_list[256];
  30.     /* Start the inode count at three, since root path should be two */
  31.     static int            inode_count = 3;
  32.  
  33.     struct path_list        *path_ptr, *prev_ptr;
  34.     const char            *p;
  35.     int                hash;
  36.  
  37.     /* Skip over device and leading '/' */
  38.     if (path[1] == ':' && path[2] == '/') path += 3;
  39.  
  40.     /* We could probably use a better hash than this */
  41.     p = path;
  42.     hash = 0;
  43.     while (*p != '\0') hash += *p++;
  44.     hash = hash & 0xff;
  45.  
  46.     /* Have we seen this string? */
  47.     path_ptr = path_list[hash];
  48.     prev_ptr = path_ptr;
  49.     while (path_ptr)
  50.     {
  51.     if (strcmp(path, path_ptr->path) == 0) break;
  52.     prev_ptr = path_ptr;
  53.     path_ptr = path_ptr->next;
  54.     }
  55.  
  56.     if (path_ptr)
  57.     /* Same string, so same inode */
  58.     buf->st_ino = path_ptr->inode;
  59.     else
  60.     {
  61.     /* New string with same hash code */
  62.     path_ptr = malloc(sizeof *path_ptr);
  63.     if (path_ptr == NULL) return -1;
  64.     path_ptr->next = NULL;
  65.     path_ptr->path = strdup(path);
  66.     if (path_ptr->path == NULL) return -1;
  67.     path_ptr->inode = inode_count;
  68.     if (prev_ptr)
  69.         prev_ptr->next = path_ptr;
  70.     else
  71.         path_list[hash] = path_ptr;
  72.     buf->st_ino = inode_count;
  73.     inode_count++;
  74.     }
  75.     return 0;
  76. }
  77.  
  78. int
  79. stat(const char *path, struct stat *buf)
  80. {
  81.     static int    stat_called_before = 0;
  82.     char    p[90];    /* Should be p[PATH_MAX+1] */
  83.     int        status;
  84.  
  85.     /* Normalize the path */
  86.     _fixpath(path, p);
  87.  
  88.     /* Work around strange bug with stat and time */
  89.     if (!stat_called_before)
  90.     {
  91.     stat_called_before = 1;
  92.     (void) time((time_t *) 0);
  93.     }
  94.  
  95.     /* Check for root path */
  96.     if (strcmp(p, "/") == 0 || strcmp(p + 1, ":/") == 0)
  97.     {
  98.     /* Handle root path as special case, stat_assist doesn't like
  99.        the root directory. */
  100.     if (p[1] == ':')
  101.     {
  102.         if (p[0] >= 'a' && p[0] <= 'z')
  103.         buf->st_dev = p[0] - 'a';
  104.         else
  105.         buf->st_dev = p[0] - 'A';
  106.     }
  107.     else
  108.         buf->st_dev = -1;    /* No device? */
  109.     buf->st_ino = 2;    /* Root path always inode 2 */
  110.     buf->st_mode = S_IFDIR | S_IREAD | S_IWRITE | S_IEXEC;
  111.     buf->st_nlink = 1;
  112.     buf->st_uid = getuid();
  113.     buf->st_gid = getgid();
  114.     buf->st_rdev = buf->st_dev;
  115.     buf->st_size = 0;
  116.     buf->st_atime = 0;
  117.     buf->st_mtime = 0;
  118.     buf->st_ctime = 0;
  119.     buf->st_blksize = 512;    /* Not always correct? */
  120.     status = 0;
  121.     }
  122.     else
  123.     {
  124.     status = stat_assist(p, buf);
  125.  
  126.     /* Make inode numbers unique */
  127.     if (status == 0) status = fixinode(p, buf);
  128.  
  129.     /* The stat_assist does something weird with st_dev, but sets
  130.        st_rdev to the drive number.  Fix st_dev. */
  131.     buf->st_dev = buf->st_rdev;
  132.  
  133.     /* Make all files owned by ourself. */
  134.     buf->st_uid = getuid();
  135.     buf->st_gid = getgid();
  136.  
  137.     /* Make all directories writable.  They always are in DOS, but
  138.        stat_assist doesn't think so. */
  139.     if (S_ISDIR(buf->st_mode)) buf->st_mode |= S_IWRITE;
  140.     }
  141.  
  142.     return status;
  143. }
  144.