home *** CD-ROM | disk | FTP | other *** search
/ Meeting Pearls 3 / Meeting_Pearls_III.iso / Pearls / texmf / source / TeX / gcclib / stat.c < prev    next >
Encoding:
C/C++ Source or Header  |  1991-11-02  |  7.4 KB  |  306 lines

  1. /* stat.c   for TeX 3.1 [ST] */
  2. /* only using `_do_stat()' (br) */
  3.  
  4. #ifndef atarist
  5. #error Please use this file only for GCC Lib (PatchLevel 62) on Atari ST !!!
  6. #endif
  7.  
  8.  
  9. /*
  10.  * stat, fstat, lstat emulation for TOS
  11.  *
  12.  * written by Eric R. Smith and Jwahar Bammi, based on the original
  13.  * from the old GCC library (which original was copyright 1988
  14.  * Memorial University).
  15.  */
  16.  
  17. #include    <assert.h>
  18. #include    <stdio.h>
  19. #include    <types.h>
  20. #include    <stat.h>
  21. #include    <ctype.h>
  22. #include    <errno.h>
  23. #include    <osbind.h>
  24. #include    <unistd.h>
  25. #include    <support.h>
  26. #include    <string.h>
  27. #include    <dirent.h>
  28. #include    <device.h>
  29. #include    "symdir.h"
  30. #include    <time.h>
  31. #include    "lib.h"
  32.  
  33. ino_t    __inode = 32;        /* used in readdir also */
  34. int    _x_Bit_set_in_stat = 0;    /* default 0, need change in emacs:sysdep.c */
  35.  
  36. DIR *__opendir_chain = 0;    /* chain of open directories from opendir */
  37.  
  38. /* date for files (like root directories) that don't have one */
  39. #define OLDDATE unixtime(0,0)
  40.  
  41. /*
  42.  * check file cache for the file whose canonical (unx2dos) name is fullname.
  43.  * this is only valid for TOS files, i.e. files that are NOT symbolic
  44.  * links. If file is not found in cache, use Fsfirst to look it up.
  45.  * All open directories (via opendir) are cached (we don't lose much by
  46.  * doing this, and it's a good heuristic for which files are going to
  47.  * need stat() in the near future; plus, opendir did Fsfirst()/Fsnext()
  48.  * already. Programs like "ls" should win big time.
  49.  *
  50.  * BUG/FEATURE: if the _lHIDE flag is set, opendir() never records the
  51.  * existence of .dir, and so stat() in an open directory won't find it.
  52.  */
  53.  
  54. struct dirent *
  55. _do_stat(fullname)
  56. char *fullname;
  57. {
  58.     char path[FILENAME_MAX], name[NAME_MAX], *tmp;
  59.     DIR *dir;
  60.     struct dirent *d;
  61.     static struct dirent dtmp;
  62.     static struct _dta    dtabuf;
  63.     struct _dta *olddta;
  64.     int r;
  65.  
  66.     strcpy(path, fullname);
  67.     if((tmp = strrchr(path, '\\'))) {
  68.         *tmp++ = 0;
  69.         _dos2unx(tmp, name);
  70.     }
  71.     else {
  72.         _dos2unx(path, name);
  73.         path[0] = 0;
  74.     }
  75.  
  76. /*
  77.  * search through the chain of open directories, 1 at a time
  78.  */
  79.     for (dir = __opendir_chain; dir; dir = dir->D_nxtdir) {
  80.         if (!strcmp(path, dir->D_path)) {
  81.             for (d = dir->D_list; d; d = d->d_next) {
  82.                 if (!strcmp(name,d->d_name) &&
  83.                     d->d_attribute != 0xff) {
  84.                     return d;
  85.                 }
  86.             }
  87.         }
  88.     }
  89.     d = &dtmp;
  90.     olddta = (struct _dta *)Fgetdta();
  91.     Fsetdta(&dtabuf);
  92.     r = Fsfirst(fullname, FA_SYSTEM|FA_HIDDEN|FA_DIR);
  93.     Fsetdta(olddta);
  94.     if (r < 0) {
  95.         errno = -r;
  96.         return NULL;
  97.     }
  98.     d->d_ino = __inode++;
  99.     d->d_time = dtabuf.dta_time;
  100.     d->d_date = dtabuf.dta_date;
  101.     d->d_attribute = dtabuf.dta_attribute;
  102.     d->d_size = dtabuf.dta_size;
  103.  
  104.     return d;
  105. }
  106.  
  107. #if 0
  108. int
  109. stat(_path, st)
  110.     const char    *_path;
  111.     struct stat    *st;
  112. {
  113.     int    rval, nval;
  114.     char    path[FILENAME_MAX];
  115.     char    *ext, drv;
  116.     int    fd;
  117.     short    magic;
  118.     struct dirent *d;
  119.     struct _device *device;
  120.  
  121.     if (!_path) {
  122.         errno = EFAULT;
  123.         return -1;
  124.     }
  125.  
  126. /*
  127.  * NOTE: the new unx2dos gives a complete, canonical TOS pathname
  128.  * (i.e. stripped of . and .., and with a drive letter). It also returns
  129.  * some useful information about what the given filename was (e.g. symlink,
  130.  * or device)
  131.  */
  132.     nval = _unx2dos(_path, path);
  133.     if (nval == _NM_DEV) {
  134.         device = _dev_dosname(path);
  135.         st->st_mode = S_IFCHR | 0600;
  136.         st->st_attr = 0xfe;
  137.         st->st_ino = st->st_rdev = device->dev;
  138.         st->st_mtime = st->st_ctime = st->st_atime = 
  139.             time((time_t *)0) - 2;
  140.         st->st_dev = 0;
  141.     /* if _tDEV is on, /dev/console & CON: are the same file */
  142.         st->st_nlink = _tDEV ? 2 : 1;
  143.         st->st_uid = geteuid();
  144.         st->st_gid = getegid();
  145.         st->st_blksize = 1024;
  146.         return 0;
  147.     }
  148.  
  149.     /* Deal with the root directory of a logical drive */
  150.     if (path[0] == '\\' && path[1] == 0) {
  151.         drv = Dgetdrv() + 'A';
  152.         goto rootdir;
  153.     }
  154.  
  155.     if ( (drv = path[0]) && path[1] == ':' &&
  156.          (path[2] == 0 || (path[2] == '\\' && path[3] == 0)) ) {
  157. rootdir:
  158.         st->st_mode = S_IFDIR | 0755;
  159.         st->st_attr = FA_DIR;
  160.         st->st_ino = isupper(drv) ? drv - 'A' : drv - 'a';
  161.         st->st_mtime = st->st_ctime = st->st_atime = OLDDATE;
  162.         goto fill_dir;
  163.     }
  164.  
  165.     /* forbid wildcards in path names */
  166.     if (index(path, '*') || index(path, '?')) {
  167.         errno = ENOENT;
  168.         return -1;
  169.     }
  170.  
  171.     if (!(d = _do_stat(path))) {
  172.     /* errno was set by _do_stat */
  173.         if (errno == ENOENT && nval == _NM_LINK) {
  174.         /* here we have a symbolic link to a deleted file */
  175.             st->st_mode = S_IFLNK | 0644;
  176.             st->st_ino = ++__inode;
  177.             st->st_attr = 0xff;
  178.             st->st_mtime = st->st_ctime = st->st_atime = OLDDATE;
  179.             st->st_size = strlen(__link_to);
  180.             st->st_blocks = 1;
  181.             st->st_nlink = 1;
  182.             goto fill_rest;
  183.         }
  184.         return -1;
  185.     }
  186.     st->st_mtime = st->st_ctime = st->st_atime =
  187.         unixtime(d->d_time, d->d_date);
  188.     st->st_ino = d->d_ino;
  189.     st->st_attr = d->d_attribute;
  190.     st->st_mode = 0644 | (d->d_attribute & FA_DIR ?
  191.                   S_IFDIR | 0111 : S_IFREG);
  192.     if (d->d_attribute & FA_RDONLY)
  193.         st->st_mode &= ~0222;    /* no write permission */
  194.     if (d->d_attribute & FA_HIDDEN)
  195.         st->st_mode &= ~0444;    /* no read permission */
  196.  
  197. /* check for a file with an executable extension */
  198.     ext = strrchr(_path, '.');
  199.     if (ext) {
  200.         if (!strcmp(ext, ".ttp") || !strcmp(ext, ".prg") ||
  201.             !strcmp(ext, ".tos") || !strcmp(ext, ".g") ||
  202.             !strcmp(ext, ".sh")     || !strcmp(ext, ".bat")) {
  203.             st->st_mode |= 0111;
  204.         }
  205.     }
  206.     if ( (st->st_mode & S_IFMT) == S_IFREG) {
  207.         if (_x_Bit_set_in_stat) {
  208.             if ((fd = Fopen(path,0)) < 0) {
  209.                 errno = -rval;
  210.                 return -1;
  211.             }
  212.             (void)Fread(fd,2,(char *)&magic);
  213.             (void)Fclose(fd);
  214.             if (magic == 0x601A) st->st_mode |= 0111;
  215.         }
  216.         st->st_size = d->d_size;
  217.         st->st_blocks = (d->d_size + 1023) / 1024;
  218.         st->st_nlink = 1; /* we dont have hard links */
  219.     } else {
  220. fill_dir:
  221.         st->st_size = 1024;
  222.         st->st_blocks = 1;
  223.         st->st_nlink = 2;    /* "foo" && "foo/.." */
  224.     }
  225.  
  226. fill_rest:
  227.     if ((drv = *path) && path[1] == ':')
  228.         st->st_dev = islower(drv) ? drv - 'a' : drv - 'A';
  229.     else
  230.         st->st_dev = Dgetdrv();
  231.     st->st_rdev = 0;
  232.     st->st_uid = geteuid();    /* the current user owns every file */
  233.     st->st_gid = getegid();
  234.     st->st_blksize = 1024;
  235.     return 0;
  236. }
  237.  
  238. #include <fcntl.h>
  239.  
  240. int fstat(fd, st)
  241. int fd;
  242. struct stat *st;
  243. {
  244.     int old;
  245.     int r;
  246.  
  247.     fd = __OPEN_INDEX(fd);
  248.     if((fd >= 0) && (fd < __NHANDLES))
  249.     {
  250. /* we should turn off links, because the name we're going to give
  251.  * to 'stat' has already been unx2dos'd
  252.  */
  253.     old = _lOK;
  254.     _lOK = 0;
  255.     r = stat(__open_stat[fd].filename, st);
  256.     _lOK = old;
  257.     return r;
  258.     }
  259.     errno = EBADF;
  260.     return -1;
  261. }
  262.  
  263. /*
  264.  * "stat" that doesn't follow symbolic links
  265.  * important exception: if _lAUTO is set and the link is an automatic
  266.  * link, follow it anyways. This allows automatic links to be aliases
  267.  * for real files (stat will correctly return the info about the
  268.  * automatic link if the real file has been deleted).
  269.  */
  270.  
  271. int
  272. lstat(_path, st)
  273.     const char *_path;
  274.     struct stat *st;
  275. {
  276.     char path[FILENAME_MAX];
  277.     int n, r, linksiz;
  278.     SYMDIR *dir;
  279.     SYMENTRY *ent;
  280.  
  281. /* _unx2dos returns _NM_LINK if the last path component was a symbolic link
  282.  * in this case, __link_name and __link_path are set to the name and path
  283.  * of the symbolic link file, and __link_to to its contents
  284.  */
  285.     n = _unx2dos(_path, path);
  286.     linksiz = strlen(__link_to);
  287.  
  288.     if (n == _NM_LINK && _lAUTO && (dir = _read_symdir(__link_path))) {
  289.         ent = _symdir_lookup(dir, __link_name);
  290.         assert(ent != 0);
  291.         if (ent->flags & SD_AUTO)
  292.             n = _NM_OK;    /* pretend that it wasn't a link*/
  293.         _free_symdir(dir);
  294.     }
  295.  
  296.     r = stat(_path, st);
  297.  
  298.     if (n != _NM_LINK || r < 0)        /* not a symlink */
  299.         return r;
  300.     st->st_size = linksiz;
  301.     st->st_blocks = (st->st_size + 1023)/1024;
  302.     st->st_mode = ((st->st_mode & ~S_IFMT) | S_IFLNK);
  303.     return 0;
  304. }
  305. #endif
  306.