home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / mint095s / unifs.c < prev    next >
C/C++ Source or Header  |  1993-08-03  |  11KB  |  548 lines

  1. /*
  2. Copyright 1991,1992 Eric R. Smith. All rights reserved.
  3.  */
  4.  
  5. /* a simple unified file system */
  6.  
  7. #include "mint.h"
  8.  
  9.  
  10. extern FILESYS bios_filesys, proc_filesys, pipe_filesys, shm_filesys;
  11.  
  12. static long    uni_root    P_((int drv, fcookie *fc));
  13. static long    uni_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  14. static long    uni_getxattr    P_((fcookie *fc, XATTR *xattr));
  15. static long    uni_chattr    P_((fcookie *fc, int attrib));
  16. static long    uni_chown    P_((fcookie *fc, int uid, int gid));
  17. static long    uni_chmode    P_((fcookie *fc, unsigned mode));
  18. static long    uni_rmdir    P_((fcookie *dir, const char *name));
  19. static long    uni_remove    P_((fcookie *dir, const char *name));
  20. static long    uni_getname    P_((fcookie *root, fcookie *dir, char *pathname));
  21. static long    uni_rename    P_((fcookie *olddir, char *oldname,
  22.                     fcookie *newdir, const char *newname));
  23. static long    uni_opendir    P_((DIR *dirh, int flags));
  24. static long    uni_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *));
  25. static long    uni_rewinddir    P_((DIR *dirh));
  26. static long    uni_closedir    P_((DIR *dirh));
  27. static long    uni_pathconf    P_((fcookie *dir, int which));
  28. static long    uni_dfree    P_((fcookie *dir, long *buf));
  29. static DEVDRV *    uni_getdev    P_((fcookie *fc, long *devsp));
  30. static long    uni_symlink    P_((fcookie *dir, const char *name, const char *to));
  31. static long    uni_readlink    P_((fcookie *fc, char *buf, int buflen));
  32.  
  33. FILESYS uni_filesys = {
  34.     (FILESYS *)0,
  35.     0,
  36.     uni_root,
  37.     uni_lookup, nocreat, uni_getdev, uni_getxattr,
  38.     uni_chattr, uni_chown, uni_chmode,
  39.     nomkdir, uni_rmdir, uni_remove, uni_getname, uni_rename,
  40.     uni_opendir, uni_readdir, uni_rewinddir, uni_closedir,
  41.     uni_pathconf, uni_dfree, nowritelabel, noreadlabel,
  42.     uni_symlink, uni_readlink, nohardlink, nofscntl, nodskchng
  43. };
  44.  
  45. /*
  46.  * structure that holds files
  47.  * if (mode & S_IFMT == S_IFDIR), then this is an alias for a drive:
  48.  *    "dev" holds the appropriate BIOS device number, and
  49.  *    "data" is meaningless
  50.  * if (mode & S_IFMT == S_IFLNK), then this is a symbolic link:
  51.  *    "dev" holds the user id of the owner, and
  52.  *    "data" points to the actual link data
  53.  */
  54.  
  55. typedef struct unifile {
  56.     char name[NAME_MAX+1];
  57.     short mode;
  58.     ushort dev;
  59.     FILESYS *fs;
  60.     void *data;
  61.     struct unifile *next;
  62. } UNIFILE;
  63.  
  64. /* the "+1" is for shared memory, which has no BIOS drive */
  65. #define UNI_DIRS NUM_DRIVES+1
  66. static UNIFILE u_drvs[UNI_DIRS];
  67. static UNIFILE *u_root = 0;
  68.  
  69. void
  70. unifs_init()
  71. {
  72.     UNIFILE *u = u_drvs;
  73.     int i;
  74.  
  75.     u_root = u;
  76.     for (i = 0; i < NUM_DRIVES; i++,u++) {
  77.         u->next = u+1;
  78.         u->mode = S_IFDIR|DEFAULT_DIRMODE;
  79.         u->dev = i;
  80.         u->fs = 0;
  81.         if (i == PROCDRV)
  82.             strcpy(u->name, "proc");
  83.         else if (i == PIPEDRV)
  84.             strcpy(u->name, "pipe");
  85.         else if (i == BIOSDRV)
  86.             strcpy(u->name, "dev");
  87.         else if (i == UNIDRV) {
  88.             (u-1)->next = u->next;    /* skip this drive */
  89.         } else {
  90.             u->name[0] = i + 'a';
  91.             u->name[1] = 0;
  92.         }
  93.     }
  94.     u->next = 0;
  95.     u->mode = S_IFDIR|DEFAULT_DIRMODE;
  96.     u->dev = SHMDEVICE;
  97.     u->fs = &shm_filesys;
  98.     strcpy(u->name, "shm");
  99. }
  100.  
  101. static long
  102. uni_root(drv, fc)
  103.     int drv;
  104.     fcookie *fc;
  105. {
  106.     if (drv == UNIDRV) {
  107.         fc->fs = &uni_filesys;
  108.         fc->dev = drv;
  109.         fc->index = 0L;
  110.         return 0;
  111.     }
  112.     fc->fs = 0;
  113.     return EINTRN;
  114. }
  115.  
  116. static long
  117. uni_lookup(dir, name, fc)
  118.     fcookie *dir;
  119.     const char *name;
  120.     fcookie *fc;
  121. {
  122.     UNIFILE *u;
  123.     long drvs;
  124.     FILESYS *fs;
  125.     extern long dosdrvs;
  126.  
  127.     TRACE("uni_lookup(%s)", name);
  128.  
  129.     if (dir->index != 0) {
  130.         DEBUG("uni_lookup: bad directory");
  131.         return EPTHNF;
  132.     }
  133. /* special case: an empty name in a directory means that directory */
  134. /* so do "." and ".." */
  135.  
  136.     if (!*name || !strcmp(name, ".") || !strcmp(name, "..")) {
  137.         *fc = *dir;
  138.         return 0;
  139.     }
  140.     drvs = drvmap() | dosdrvs | PSEUDODRVS;
  141. /*
  142.  * OK, check the list of aliases and special directories
  143.  */
  144.     for (u = u_root; u; u = u->next) {
  145.         if (!stricmp(name, u->name)) {
  146.             if ( (u->mode & S_IFMT) == S_IFDIR ) {
  147.                 if (u->dev >= NUM_DRIVES) {
  148.                     fs = u->fs;
  149.                     return (*fs->root)(u->dev,fc);
  150.                 }
  151.                 if ((drvs & (1L << u->dev)) == 0)
  152.                     return EPTHNF;
  153.                 *fc = curproc->root[u->dev];
  154.                 if (!fc->fs) {        /* drive changed? */
  155.                     changedrv(fc->dev);
  156.                     *fc = curproc->root[u->dev];
  157.                     if (!fc->fs)
  158.                         return EPTHNF;
  159.                 }
  160.             } else {        /* a symbolic link */
  161.                 fc->fs = &uni_filesys;
  162.                 fc->dev = UNIDRV;
  163.                 fc->index = (long)u;
  164.             }
  165.             return 0;
  166.         }
  167.     }
  168.     DEBUG("uni_lookup: name (%s) not found", name);
  169.     return EFILNF;
  170. }
  171.  
  172. static long
  173. uni_getxattr(fc, xattr)
  174.     fcookie *fc;
  175.     XATTR *xattr;
  176. {
  177.     UNIFILE *u = (UNIFILE *)fc->index;
  178.  
  179.     if (fc->fs != &uni_filesys) {
  180.         ALERT("ERROR: wrong file system getxattr called");
  181.         return EINTRN;
  182.     }
  183.  
  184.     xattr->index = fc->index;
  185.     xattr->dev = fc->dev;
  186.     xattr->nlink = 1;
  187.     xattr->blksize = 1;
  188.  
  189. /* If "u" is null, then we have the root directory, otherwise
  190.  * we use the UNIFILE structure to get the info about it
  191.  */
  192.     if (!u || ( (u->mode & S_IFMT) == S_IFDIR )) {
  193.         xattr->uid = xattr->gid = 0;
  194.         xattr->size = xattr->nblocks = 0;
  195.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  196.         xattr->attr = FA_DIR;
  197.     } else {
  198.         xattr->uid = u->dev;
  199.         xattr->gid = 0;
  200.         xattr->size = xattr->nblocks = strlen(u->data) + 1;
  201.         xattr->mode = u->mode;
  202.         xattr->attr = 0;
  203.     }
  204.     xattr->mtime = xattr->atime = xattr->ctime = 0;
  205.     xattr->mdate = xattr->adate = xattr->cdate = 0;
  206.     return 0;
  207. }
  208.  
  209. static long
  210. uni_chattr(dir, attrib)
  211.     fcookie *dir;
  212.     int attrib;
  213. {
  214.     return EACCDN;
  215. }
  216.  
  217. static long
  218. uni_chown(dir, uid, gid)
  219.     fcookie *dir;
  220.     int uid, gid;
  221. {
  222.     return EINVFN;
  223. }
  224.  
  225. static long
  226. uni_chmode(dir, mode)
  227.     fcookie *dir;
  228.     unsigned mode;
  229. {
  230.     return EINVFN;
  231. }
  232.  
  233. static long
  234. uni_rmdir(dir, name)
  235.     fcookie *dir;
  236.     const char *name;
  237. {
  238.     long r;
  239.  
  240.     r = uni_remove(dir, name);
  241.     if (r == EFILNF) r = EPTHNF;
  242.     return r;
  243. }
  244.  
  245. static long
  246. uni_remove(dir, name)
  247.     fcookie *dir;
  248.     const char *name;
  249. {
  250.     UNIFILE *u, *lastu;
  251.  
  252.     lastu = 0;
  253.     u = u_root;
  254.     while (u) {
  255.         if (!strncmp(u->name, name, NAME_MAX)) {
  256.             if ( (u->mode & S_IFMT) != S_IFLNK ) return EFILNF;
  257.             kfree(u->data);
  258.             if (lastu)
  259.                 lastu->next = u->next;
  260.             else
  261.                 u_root = u->next;
  262.             kfree(u);
  263.             return 0;
  264.         }
  265.         lastu = u;
  266.         u = u->next;
  267.     }
  268.     return EFILNF;
  269. }
  270.  
  271. static long
  272. uni_getname(root, dir, pathname)
  273.     fcookie *root, *dir; char *pathname;
  274. {
  275.     FILESYS *fs;
  276.     UNIFILE *u;
  277.     char *n;
  278.     fcookie relto;
  279.  
  280.     fs = dir->fs;
  281.     if (dir->dev == UNIDRV) {
  282.         *pathname = 0;
  283.         return 0;
  284.     }
  285.  
  286.     for (u = u_root; u; u = u->next) {
  287.         if (dir->dev == u->dev && (u->mode & S_IFMT) == S_IFDIR) {
  288.             *pathname++ = '\\';
  289.             for (n = u->name; *n; )
  290.                 *pathname++ = *n++;
  291.             break;
  292.         }
  293.     }
  294.  
  295.     if (!u) {
  296.         ALERT("unifs: couldn't match a drive with a directory");
  297.         return EPTHNF;
  298.     }
  299.  
  300.     if (dir->dev >= NUM_DRIVES) {
  301.         if ((*fs->root)(dir->dev, &relto) == 0) {
  302.             return (*fs->getname)(&relto, dir, pathname);
  303.         } else {
  304.             *pathname++ = 0;
  305.             return EINTRN;
  306.         }
  307.     }
  308.  
  309.     if (curproc->root[dir->dev].fs != fs) {
  310.         ALERT("unifs: drive's file system doesn't match directory's");
  311.         return EINTRN;
  312.     }
  313.  
  314.     return (*fs->getname)(&curproc->root[dir->dev], dir, pathname);
  315. }
  316.  
  317. static long
  318. uni_rename(olddir, oldname, newdir, newname)
  319.     fcookie *olddir;
  320.     char *oldname;
  321.     fcookie *newdir;
  322.     const char *newname;
  323. {
  324.     UNIFILE *u = 0;
  325.     fcookie fc;
  326.     long r;
  327.  
  328.     for (u = u_root; u; u = u->next) {
  329.         if (!stricmp(u->name, oldname))
  330.             break;
  331.     }
  332.  
  333.     if (!u) {
  334.         DEBUG("uni_rename: old file not found");
  335.         return EFILNF;
  336.     }
  337.  
  338. /* the new name is not allowed to exist! */
  339.     r = uni_lookup(newdir, newname, &fc);
  340.     if (r != EFILNF) {
  341.         DEBUG("uni_rename: error %ld", r);
  342.         return (r == 0) ? EACCDN : r;
  343.     }
  344.  
  345.     (void)strncpy(u->name, newname, NAME_MAX);
  346.     return 0;
  347. }
  348.  
  349. static long
  350. uni_opendir(dirh, flags)
  351.     DIR *dirh;
  352.     int flags;
  353. {
  354.     if (dirh->fc.index != 0) {
  355.         DEBUG("uni_opendir: bad directory");
  356.         return EPTHNF;
  357.     }
  358.     dirh->index = 0;
  359.     return 0;
  360. }
  361.  
  362.  
  363. static long
  364. uni_readdir(dirh, name, namelen, fc)
  365.     DIR *dirh;
  366.     char *name;
  367.     int namelen;
  368.     fcookie *fc;
  369. {
  370.     long map;
  371.     char *dirname;
  372.     int i;
  373.     int giveindex = (dirh->flags == 0);
  374.     UNIFILE *u;
  375.     long index;
  376.     extern long dosdrvs;
  377.     long r;
  378.  
  379.     map = dosdrvs | drvmap() | PSEUDODRVS;
  380.     i = dirh->index++;
  381.     u = u_root;
  382.     while (i > 0) {
  383.         --i;
  384.         u = u->next;
  385.         if (!u)
  386.             break;
  387.     }
  388. tryagain:
  389.     if (!u) return ENMFIL;
  390.  
  391.     dirname = u->name;
  392.     index = (long)u;
  393.     if ( (u->mode & S_IFMT) == S_IFDIR ) {
  394. /* make sure the drive really exists */
  395.         if ( u->dev >= NUM_DRIVES) {
  396.             r = (*u->fs->root)(u->dev,fc);
  397.             if (r) {
  398.             fc->fs = &uni_filesys;
  399.             fc->index = 0;
  400.             fc->dev = u->dev;
  401.             }
  402.         } else {
  403.             if ((map & (1L << u->dev)) == 0 ) {
  404.             dirh->index++;
  405.             u = u->next;
  406.             goto tryagain;
  407.             }
  408.             *fc = curproc->root[u->dev];
  409.             if (!fc->fs) {    /* drive not yet initialized */
  410.         /* use default attributes */
  411.             fc->fs = &uni_filesys;
  412.             fc->index = 0;
  413.             fc->dev = u->dev;
  414.             }
  415.         }
  416.     } else {        /* a symbolic link */
  417.         fc->fs = &uni_filesys;
  418.         fc->dev = UNIDRV;
  419.         fc->index = (long)u;
  420.     }
  421.  
  422.     if (giveindex) {
  423.         namelen -= sizeof(long);
  424.         if (namelen <= 0) return ERANGE;
  425.         *((long *)name) = index;
  426.         name += sizeof(long);
  427.     }
  428.     strncpy(name, dirname, namelen-1);
  429.     if (strlen(name) < strlen(dirname))
  430.         return ENAMETOOLONG;
  431.     return 0;
  432. }
  433.  
  434. static long
  435. uni_rewinddir(dirh)
  436.     DIR *dirh;
  437. {
  438.     dirh->index = 0;
  439.     return 0;
  440. }
  441.  
  442. static long
  443. uni_closedir(dirh)
  444.     DIR *dirh;
  445. {
  446.     return 0;
  447. }
  448.  
  449. static long
  450. uni_pathconf(dir, which)
  451.     fcookie *dir;
  452.     int which;
  453. {
  454.     switch(which) {
  455.     case -1:
  456.         return DP_MAXREQ;
  457.     case DP_IOPEN:
  458.         return 0;        /* no files to open */
  459.     case DP_MAXLINKS:
  460.         return 1;        /* no hard links available */
  461.     case DP_PATHMAX:
  462.         return PATH_MAX;
  463.     case DP_NAMEMAX:
  464.         return NAME_MAX;
  465.     case DP_ATOMIC:
  466.         return 1;        /* no atomic writes */
  467.     case DP_TRUNC:
  468.         return DP_AUTOTRUNC;
  469.     case DP_CASE:
  470.         return DP_CASEINSENS;
  471.     default:
  472.         return EINVFN;
  473.     }
  474. }
  475.  
  476. static long
  477. uni_dfree(dir, buf)
  478.     fcookie *dir;
  479.     long *buf;
  480. {
  481.     buf[0] = 0;    /* number of free clusters */
  482.     buf[1] = 0;    /* total number of clusters */
  483.     buf[2] = 1;    /* sector size (bytes) */
  484.     buf[3] = 1;    /* cluster size (sectors) */
  485.     return 0;
  486. }
  487.  
  488. static DEVDRV *
  489. uni_getdev(fc, devsp)
  490.     fcookie *fc;
  491.     long *devsp;
  492. {
  493.     *devsp = EACCDN;
  494.     return 0;
  495. }
  496.  
  497. static long
  498. uni_symlink(dir, name, to)
  499.     fcookie *dir;
  500.     const char *name;
  501.     const char *to;
  502. {
  503.     UNIFILE *u;
  504.     fcookie fc;
  505.     long r;
  506.  
  507.     r = uni_lookup(dir, name, &fc);
  508.     if (r == 0) return EACCDN;    /* file already exists */
  509.     if (r != EFILNF) return r;    /* some other error */
  510.  
  511.     u = kmalloc(SIZEOF(UNIFILE));
  512.     if (!u) return EACCDN;
  513.  
  514.     strncpy(u->name, name, NAME_MAX);
  515.     u->name[NAME_MAX] = 0;
  516.  
  517.     u->data = kmalloc((long)strlen(to)+1);
  518.     if (!u->data) {
  519.         kfree(u);
  520.         return EACCDN;
  521.     }
  522.     strcpy(u->data, to);
  523.     u->mode = S_IFLNK | DEFAULT_DIRMODE;
  524.     u->dev = curproc->ruid;
  525.     u->next = u_root;
  526.     u->fs = &uni_filesys;
  527.     u_root = u;
  528.     return 0;
  529. }
  530.  
  531. static long
  532. uni_readlink(fc, buf, buflen)
  533.     fcookie *fc;
  534.     char *buf;
  535.     int buflen;
  536. {
  537.     UNIFILE *u;
  538.  
  539.     u = (UNIFILE *)fc->index;
  540.     assert(u);
  541.     assert((u->mode & S_IFMT) == S_IFLNK);
  542.     assert(u->data);
  543.     strncpy(buf, u->data, buflen);
  544.     if (strlen(u->data) >= buflen)
  545.         return ENAMETOOLONG;
  546.     return 0;
  547. }
  548.