home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / mint104s.zoo / mint.src / unifs.c < prev    next >
C/C++ Source or Header  |  1993-03-08  |  13KB  |  618 lines

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