Subversion Repositories Kolibri OS

Rev

Blame | Last modification | View Log | Download | RSS feed

  1. /*
  2.   Copyright (c) 1990-2000 Info-ZIP.  All rights reserved.
  3.  
  4.   See the accompanying file LICENSE, version 2000-Apr-09 or later
  5.   (the contents of which are also included in unzip.h) for terms of use.
  6.   If, for some reason, all these files are missing, the Info-ZIP license
  7.   also may be found at:  ftp://ftp.info-zip.org/pub/infozip/license.html
  8. */
  9. #pragma library
  10. #include <stdio.h>
  11. #include <stdlib.h>
  12. #include <errno.h>
  13. #include <string.h>
  14. #include <sc.h>
  15. #include <peek.h>
  16. #include <lub.h>
  17. #include <fdb.h>
  18. #include <fsa.h>
  19. #include "theos/stat.h"
  20.  
  21. /* replacement for standard library functions stat and fstat */
  22.  
  23. int _stat_(struct stat* st, struct fdb* fdb);
  24. int _dstat_(struct stat* st);
  25.  
  26. #define peekucb() peeknuc()
  27.  
  28. /* map THEOS protection code to Unix modes */
  29.  
  30. unsigned short _tm2um_(char protect)
  31. {
  32.     unsigned short umask = 0;
  33.  
  34.     if (!(protect & _FDB_READ_PROTECT))
  35.         umask = S_IRUSR|S_IRGRP;
  36.  
  37.     if (!(protect & _FDB_WRITE_PROTECT))
  38.         umask |= S_IWUSR|S_IWGRP;
  39.  
  40.     if (!(protect & _FDB_EXECUTE_PROTECT))
  41.         umask |= S_IXUSR|S_IXGRP;
  42.  
  43.     if (!(protect & _FDB_ERASE_PROTECT))
  44.         umask |= S_IEUSR|S_IEGRP;
  45.  
  46.     if (!(protect & _FDB_SHARED_READ_PROTECT)) {
  47.         if (_osmajor > 3)
  48.             umask |= S_IROTH|S_IXOTH;
  49.         else
  50.             umask |= S_IROTH;
  51.     }
  52.  
  53.     if (!(protect & _FDB_SHARED_WRITE_PROTECT))
  54.         umask |= S_IWOTH;
  55.  
  56.     if (!(protect & _FDB_MODIFIED)) {
  57.         if (_osmajor > 3)
  58.             umask |= S_IMODF;
  59.         else
  60.             umask |= S_IXOTH;
  61.     }
  62.  
  63.     if (protect & _FDB_NOT_HIDDEN)
  64.         umask |= S_INHID;
  65.  
  66.     return umask;
  67. }
  68.  
  69. /* map Unix modes to THEOS protections */
  70.  
  71. char _um2tm_(unsigned short mask)
  72. {
  73.     char protect = 0;
  74.  
  75.     if (!(mask & (S_IRUSR|S_IRGRP)))
  76.         protect |= _FDB_READ_PROTECT;
  77.  
  78.     if (!(mask & (S_IWUSR|S_IWGRP)))
  79.         protect |= _FDB_WRITE_PROTECT;
  80.  
  81.     if (!(mask & (S_IXUSR|S_IXGRP)))
  82.         protect |= _FDB_EXECUTE_PROTECT;
  83.  
  84.     if (!(mask & (S_IEUSR|S_IEGRP)))
  85.         protect |= _FDB_ERASE_PROTECT;
  86.  
  87.     if (_osmajor < 4) {
  88.         if (!(mask & S_IROTH))
  89.             protect |= _FDB_SHARED_READ_PROTECT;
  90.     } else {
  91.         if (!(mask & (S_IROTH|S_IXOTH)))
  92.             protect |= _FDB_SHARED_READ_PROTECT;
  93.     }
  94.  
  95.     if (!(mask & S_IWOTH))
  96.         protect |= _FDB_SHARED_WRITE_PROTECT;
  97.  
  98.     if (mask & S_IMODF && _osmajor > 3)
  99.         protect |= _FDB_MODIFIED;
  100.  
  101.     if (mask & S_INHID && _osmajor > 3)
  102.         protect |= _FDB_NOT_HIDDEN;
  103.  
  104.     return protect;
  105. }
  106.  
  107. /* root directory stat */
  108.  
  109. static int rdirstat(char* fn, struct stat *st)
  110. {
  111.     register char* p = strchr(fn, ':');
  112.     char drive;
  113.  
  114.     drive = p ? p[1] : 'S';
  115.  
  116.     if (drive >= 'a' && drive <= 'Z')
  117.         drive -= 0x40;
  118.  
  119.     memset(st, 0, sizeof(struct stat));
  120.  
  121.     if (getlub(drive - 'A') != 255) {
  122.         st->st_org = _FDB_STAT_DIRECTORY;
  123.         st->st_mode = S_IFDIR|S_IRUSR|S_IWUSR|S_IROTH|S_IWOTH;
  124.         st->st_nlink = 1;
  125.         st->st_dev = st->st_rdev = drive - 'A';
  126.         st->st_uid = st->st_gid = getuid();
  127.         st->st_protect = _FDB_ERASE_PROTECT;
  128.         return 0;
  129.     }
  130.     errno = _errnum = ENOENT;
  131.     _errarg = fn;
  132.     return -1;
  133. }
  134.  
  135. /* file stat */
  136.  
  137. int _stat(const char *fn, struct stat *st)
  138. {
  139.     char buf[256], buf2[256];
  140.     char *ifn;
  141.     register struct fdb *fdb;
  142.     register char *p;
  143.  
  144.     if ((ifn = (char *)malloc(strlen(fn)+1)) == NULL) {
  145.         errno = _errnum = ENOMEM;
  146.         return -1;
  147.     }
  148.  
  149.     if (p = strrchr(ifn, ':'))
  150.         *p = 0;
  151.  
  152.     /* on current drive ./:d and .:m point to current dir
  153.      * on another drive to root directory */
  154.  
  155.     if (! strcmp(ifn, "/") || ! strcmp(ifn, ".") || ! strcmp(ifn, "./")) {
  156.         if (p == NULL) {
  157.             free(ifn);
  158.             /* current dir on current drive */
  159.             ifn = getcwd(buf2, 256);
  160.             /* getcwd returns NULL on root dir on drive S */
  161.             if (ifn == NULL)
  162.                 strcpy(ifn = buf2, "/:S");
  163.             /* getcwd returns /:d on root dir on any other drive */
  164.             if (ifn[1] == ':')
  165.                 return rdirstat(ifn, st);
  166.         } else {
  167.             int rstat;
  168.             *p = ':';
  169.             rstat = rdirstat(ifn, st);
  170.             free(ifn);
  171.             return rstat;
  172.         }
  173.     }
  174.  
  175.     if (p)
  176.         *p = ':';
  177.  
  178.     strcpy(buf2, ifn);
  179.     /* remove trailing slash before optional disk name */
  180.     if (p = strrchr(buf2, '/')) {
  181.         if (p[1] == ':') {
  182.             *p = p[1];
  183.             p[1] = p[2];
  184.             p[2] = p[3];
  185.         } else if (p[1] == '\0')
  186.             *p = '\0';
  187.     }
  188.     /* if ifn is a file get file directory block structure and device */
  189.     if (fdb = _locate(buf2, buf, &st->st_dev)) {
  190.         /* is it a file from another user... */
  191.         if (strchr(buf2, '\\')
  192.         /* a public system file */
  193.           || fdb->fileowner == 0
  194.         /* or a file from the current user account ? */
  195.           || fdb->fileowner == getuid()) {
  196.             /* yes, return stat */
  197.             return _stat_(st, fdb);
  198.         } else {
  199.             /* no, say file doesn't exist */
  200.             errno = _errnum = ENOENT;
  201.             _errarg = fn;
  202.             return -1;
  203.         }
  204.     }
  205.     /* else should be a device */
  206.     st->st_rdev = st->st_dev = _lub_name(*ifn == ':' ? ifn+1 : ifn);
  207.  
  208.     free(ifn);
  209.     if (st->st_dev != -1 && getlub(st->st_dev) != 255)
  210.         return _dstat_(st);
  211.  
  212.     errno = _errnum = ENOENT;
  213.     _errarg = fn;
  214.     return -1;
  215. }
  216.  
  217. int _fstat(int fd, struct stat *st)
  218. {
  219.     unsigned short fsanum;
  220.     struct fsa fsa;
  221.     register FILE *fp;
  222.     int status;
  223.     register int i;
  224.     register char *p;
  225.  
  226.     if (fd < FOPEN_MAX) {
  227.         fp = &stdin[fd];
  228.         if (_fcntl(fp,1,0) & 0x80) {
  229.             fsanum = (unsigned short) _fcntl(fp,83,0);
  230.             st->st_dev = (unsigned short) _fcntl(fp,5,0);
  231.  
  232.             if (st->st_dev >= A_DISK && st->st_dev <= Z_DISK) {
  233.                 for (i = 0, fsanum *= sizeof(fsa), p = (char *) &fsa;
  234.                      i < (sizeof(fsa));
  235.                      i++, fsanum++, p++)
  236.                     *p = _peekfsa((char *) fsanum);
  237.                 status = _stat_(st, (struct fdb*) &fsa);
  238.                 if ((st->st_blksize = _fcntl(fp,817,0)) == 0)
  239.                     st->st_blksize = BUFSIZ;
  240.                 return status;
  241.             }
  242.             return _dstat_(st);
  243.         }
  244.     }
  245.     errno = _errnum = EBADF;
  246.     return -1;
  247. }
  248.  
  249. static int _isprt(int dev)
  250. {
  251.     return IS_PRT_LUB(dev);
  252. }
  253.  
  254. /* device stat */
  255.  
  256. int _dstat_(st)
  257. register struct stat* st;
  258. {
  259.     register struct ucb* ucb;
  260.  
  261.     ucb = getucb(st->st_dev);
  262.     st->st_ino = 0;
  263.     if (st->st_dev <= Z_DISK
  264.      || (st->st_dev >= TAPE1 && st->st_dev <= TAPE4)) {
  265.         st->st_mode = S_IFBLK | S_IWUSR | S_IRUSR;
  266.         if (peekucb(&ucb->devowner) == 255)
  267.             st->st_mode |= S_IWGRP | S_IWOTH | S_IRGRP | S_IROTH;
  268.     } else {
  269.         st->st_mode = S_IFCHR | S_IWUSR;
  270.         if (_isprt(st->st_dev))
  271.             st->st_mode |= S_IRUSR;
  272.         if (peekucb(&ucb->devowner) == 255) {
  273.             st->st_mode |= S_IWGRP | S_IWOTH;
  274.             if (_isprt(st->st_dev))
  275.                 st->st_mode |= S_IRGRP | S_IROTH;
  276.         }
  277.     }
  278.     st->st_nlink = 1;
  279.     st->st_uid = st->st_gid = getuid();
  280.     st->st_size = 0;
  281.     st->st_atime = st->st_mtime = st->st_ctime = 0;
  282.     st->st_rlen = 0;
  283.     st->st_klen = 0;
  284.     st->st_grow = 0;
  285.     st->st_blksize = 0;
  286.     return 0;
  287. }
  288.  
  289. /* regular file stat */
  290.  
  291. int _stat_(st, fdb)
  292. register struct stat* st;
  293. register struct fdb* fdb;
  294. {
  295.     st->st_rdev = st->st_dev;
  296.     st->st_ino = 0;
  297.     st->st_org = fdb->filestat;
  298.  
  299.     switch (fdb->filestat) {
  300.     case _FDB_STAT_LIBRARY:         st->st_mode = S_IFLIB;  break;
  301.     case _FDB_STAT_DIRECTORY:       st->st_mode = S_IFDIR;  break;
  302.     case _FDB_STAT_STREAM:          st->st_mode = S_IFREG;  break;
  303.     case _FDB_STAT_RELATIVE:        st->st_mode = S_IFREL;  break;
  304.     case _FDB_STAT_KEYED:           st->st_mode = S_IFKEY;  break;
  305.     case _FDB_STAT_INDEXED:         st->st_mode = S_IFIND;  break;
  306.     case _FDB_STAT_RANDOM:          st->st_mode = S_IFRND;  break;
  307.     case _FDB_STAT_PROGRAM:         st->st_mode = S_IFR16;  break;
  308.     case _FDB_STAT_16_BIT_PROGRAM:  st->st_mode = S_IFP16;  break;
  309.     case _FDB_STAT_32_BIT_PROGRAM:  st->st_mode = S_IFP32;  break;
  310.     }
  311.  
  312.     st->st_mode |= _tm2um_(st->st_protect = fdb->protect);
  313.     st->st_nlink = 1;
  314.     st->st_uid = st->st_gid = fdb->fileowner;
  315.     st->st_size = fdb->filesize;
  316.     st->st_atime = st->st_mtime = st->st_ctime = getfiledate(fdb);
  317.     st->st_rlen = fdb->reclen;
  318.     st->st_klen = fdb->keylen;
  319.     st->st_grow = fdb->filegrow;
  320.     st->st_blksize = 0;
  321.     return 0;
  322. }
  323.  
  324. #include <direct.h>
  325.  
  326. struct dirent* _opendir(const char* dirpath)
  327. {
  328.     int l;
  329.     char *p;
  330.     struct dirent* dir;
  331.     char *mypath = NULL;
  332.  
  333.     if (dirpath != NULL &&
  334.         (mypath = (char *)malloc(strlen(dirpath)+1)) == NULL) {
  335.         errno = _errnum = ENOMEM;
  336.         return NULL;
  337.     }
  338.  
  339.     if (mypath) {
  340.         l = strlen(mypath);
  341.         if (l) {
  342.             p = dirpath + l - 1;
  343.             if (*p == '/') {
  344.                 *p = '\0';
  345.                 dir = opendir(dirpath);
  346.                 *p = '/';
  347.                 return dir;
  348.             }
  349.         }
  350.  
  351.     }
  352.     return opendir(mypath);
  353. }
  354.