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

  1. /*
  2. Copyright 1992 Eric R. Smith. All rights reserved.
  3.  */
  4.  
  5. /* Shared memory file system */
  6.  
  7. #include "mint.h"
  8.  
  9.  
  10. static long    shm_root    P_((int drv, fcookie *fc));
  11. static long    shm_creat    P_((fcookie *dir, const char *name, unsigned mode,
  12.                     int attrib, fcookie *fc));
  13. static long    shm_lookup    P_((fcookie *dir, const char *name, fcookie *fc));
  14. static long    shm_getxattr    P_((fcookie *fc, XATTR *xattr));
  15. static long    shm_chattr    P_((fcookie *fc, int attrib));
  16. static long    shm_chown    P_((fcookie *fc, int uid, int gid));
  17. static long    shm_chmode    P_((fcookie *fc, unsigned mode));
  18. static long    shm_rmdir    P_((fcookie *dir, const char *name));
  19. static long    shm_remove    P_((fcookie *dir, const char *name));
  20. static long    shm_getname    P_((fcookie *root, fcookie *dir, char *pathname));
  21. static long    shm_rename    P_((fcookie *olddir, char *oldname,
  22.                     fcookie *newdir, const char *newname));
  23. static long    shm_opendir    P_((DIR *dirh, int flags));
  24. static long    shm_readdir    P_((DIR *dirh, char *nm, int nmlen, fcookie *));
  25. static long    shm_rewinddir    P_((DIR *dirh));
  26. static long    shm_closedir    P_((DIR *dirh));
  27. static long    shm_pathconf    P_((fcookie *dir, int which));
  28. static long    shm_dfree    P_((fcookie *dir, long *buf));
  29. static DEVDRV *    shm_getdev    P_((fcookie *fc, long *devsp));
  30.  
  31. static long    shm_open    P_((FILEPTR *f));
  32. static long    shm_write    P_((FILEPTR *f, const char *buf, long bytes));
  33. static long    shm_read    P_((FILEPTR *f, char *buf, long bytes));
  34. static long    shm_lseek    P_((FILEPTR *f, long where, int whence));
  35. static long    shm_ioctl    P_((FILEPTR *f, int mode, void *buf));
  36. static long    shm_datime    P_((FILEPTR *f, short *time, int rwflag));
  37. static long    shm_close    P_((FILEPTR *f, int pid));
  38.  
  39. /* dummy routines from biosfs.c */
  40. extern long    null_select    P_((FILEPTR *f, long p, int mode));
  41. extern void    null_unselect    P_((FILEPTR *f, long p, int mode));
  42.  
  43. static short shmtime, shmdate;
  44.  
  45. #define SHMNAME_MAX 15
  46.  
  47. typedef struct shmfile {
  48.     struct shmfile *next;
  49.     char filename[SHMNAME_MAX+1];
  50.     int uid, gid;
  51.     short time, date;
  52.     unsigned mode;
  53.     int inuse;
  54.     MEMREGION *reg;
  55. } SHMFILE;
  56.  
  57. SHMFILE *shmroot = 0;
  58.  
  59. DEVDRV shm_device = {
  60.     shm_open, shm_write, shm_read, shm_lseek, shm_ioctl, shm_datime,
  61.     shm_close, null_select, null_unselect
  62. };
  63.  
  64. FILESYS shm_filesys = {
  65.     (FILESYS *)0,
  66.     0,
  67.     shm_root,
  68.     shm_lookup, shm_creat, shm_getdev, shm_getxattr,
  69.     shm_chattr, shm_chown, shm_chmode,
  70.     nomkdir, shm_rmdir, shm_remove, shm_getname, shm_rename,
  71.     shm_opendir, shm_readdir, shm_rewinddir, shm_closedir,
  72.     shm_pathconf, shm_dfree,
  73.     nowritelabel, noreadlabel, nosymlink, noreadlink, nohardlink,
  74.     nofscntl, nodskchng
  75. };
  76.  
  77. long
  78. shm_root(drv, fc)
  79.     int drv;
  80.     fcookie *fc;
  81. {
  82.     if (drv == SHMDEVICE) {
  83.         fc->fs = &shm_filesys;
  84.         fc->dev = drv;
  85.         fc->index = 0L;
  86.         return 0;
  87.     }
  88.     fc->fs = 0;
  89.     return EINTRN;
  90. }
  91.  
  92. static long
  93. shm_lookup(dir, name, fc)
  94.     fcookie *dir;
  95.     const char *name;
  96.     fcookie *fc;
  97. {
  98.     SHMFILE *s;
  99.  
  100.     if (dir->index != 0) {
  101.         DEBUG("shm_lookup: bad directory");
  102.         return EPTHNF;
  103.     }
  104.  
  105. /* special case: an empty name in a directory means that directory */
  106. /* so does "." */
  107.     if (!*name || (name[0] == '.' && name[1] == 0)) {
  108.         *fc = *dir;
  109.         return 0;
  110.     }
  111.  
  112. /* another special case: ".." could be a mount point */
  113.     if (!strcmp(name, "..")) {
  114.         *fc = *dir;
  115.         return EMOUNT;
  116.     }
  117.  
  118.     for (s = shmroot; s; s = s->next) {
  119.         if (!stricmp(s->filename,name))
  120.             break;
  121.     }
  122.  
  123.     if (!s) {
  124.         DEBUG("shm_lookup: name not found");
  125.         return EFILNF;
  126.     } else {
  127.         fc->index = (long)s;
  128.         fc->fs = &shm_filesys;
  129.         fc->dev = SHMDEVICE;
  130.     }
  131.     return 0;
  132. }
  133.  
  134. static long
  135. shm_getxattr(fc, xattr)
  136.     fcookie *fc;
  137.     XATTR *xattr;
  138. {
  139.     SHMFILE *s;
  140.  
  141.     xattr->blksize = 1;
  142.     if (fc->index == 0) {
  143.         /* the root directory */
  144.         xattr->index = 0;
  145.         xattr->dev = SHMDEVICE;
  146.         xattr->nlink = 1;
  147.         xattr->uid = xattr->gid = 0;
  148.         xattr->size = xattr->nblocks = 0;
  149.         xattr->mtime = xattr->atime = xattr->ctime = shmtime;
  150.         xattr->mdate = xattr->adate = xattr->cdate = shmdate;
  151.         xattr->mode = S_IFDIR | DEFAULT_DIRMODE;
  152.         xattr->attr = FA_DIR;
  153.         return 0;
  154.     }
  155.  
  156.     s = (SHMFILE *)fc->index;
  157.     xattr->index = (long) s;
  158.     xattr->dev = SHMDEVICE;
  159.     xattr->nlink = 1;
  160.     xattr->uid = s->uid; xattr->gid = s->gid;
  161.     if (s->reg)
  162.         xattr->size = xattr->nblocks = s->reg->len;
  163.     else
  164.         xattr->size = xattr->nblocks = 0;
  165.  
  166.     xattr->mtime = xattr->ctime = xattr->atime = s->time;
  167.     xattr->mdate = xattr->cdate = xattr->adate = s->date;
  168.     xattr->mode = S_IMEM | S_IRUSR | S_IWUSR;
  169.     xattr->attr = 0;
  170.     return 0;
  171. }
  172.  
  173. static long
  174. shm_chattr(fc, attrib)
  175.     fcookie *fc;
  176.     int attrib;
  177. {
  178.     return 0;
  179. }
  180.  
  181. static long
  182. shm_chown(fc, uid, gid)
  183.     fcookie *fc;
  184.     int uid, gid;
  185. {
  186.     SHMFILE *s;
  187.  
  188.     s = (SHMFILE *)fc->index;
  189.     if (!s)
  190.         return EINVFN;
  191.     s->uid = uid;
  192.     s->gid = gid;
  193.     return 0;
  194. }
  195.  
  196. static long
  197. shm_chmode(fc, mode)
  198.     fcookie *fc;
  199.     unsigned mode;
  200. {
  201.     SHMFILE *s;
  202.  
  203.     s = (SHMFILE *)fc->index;
  204.     if (!s)
  205.         return EINVFN;
  206.     s->mode = mode;
  207.     return 0;
  208. }
  209.  
  210. static long
  211. shm_rmdir(dir, name)
  212.     fcookie *dir;
  213.     const char *name;
  214. {
  215.     return EPTHNF;
  216. }
  217.  
  218. static long
  219. shm_remove(dir, name)
  220.     fcookie *dir;
  221.     const char *name;
  222. {
  223.     SHMFILE *s, **old;
  224.  
  225.     if (dir->index != 0)
  226.         return EPTHNF;
  227.  
  228.     old = &shmroot;
  229.     for (s = shmroot; s; s = s->next) {
  230.         if (!stricmp(s->filename, name))
  231.             break;
  232.         old = &s->next;
  233.     }
  234.     if (!s)
  235.         return EFILNF;
  236.     if (s->inuse)
  237.         return EACCDN;
  238.     *old = s->next;
  239.  
  240.     s->reg->links--;
  241.     if (s->reg->links <= 0) {
  242.         free_region(s->reg);
  243.     }
  244.     kfree(s);
  245.     shmtime = timestamp;
  246.     shmdate = datestamp;
  247.     return 0;
  248. }
  249.  
  250. static long
  251. shm_getname(root, dir, pathname)
  252.     fcookie *root, *dir; char *pathname;
  253. {
  254.     *pathname = 0;
  255.     return 0;
  256. }
  257.  
  258. static long
  259. shm_rename(olddir, oldname, newdir, newname)
  260.     fcookie *olddir;
  261.     char *oldname;
  262.     fcookie *newdir;
  263.     const char *newname;
  264. {
  265.     SHMFILE *s;
  266.  
  267.     if (olddir->index != 0 || newdir->index != 0)
  268.         return EPTHNF;
  269.  
  270. /* verify that "newname" doesn't exist */
  271.     for (s = shmroot; s; s = s->next)
  272.         if (!stricmp(s->filename, newname))
  273.             return EACCDN;
  274.  
  275.     for (s = shmroot; s; s = s->next)
  276.         if (!stricmp(s->filename, oldname))
  277.             break;
  278.     if (!s)
  279.         return EFILNF;
  280.  
  281.     strncpy(s->filename, newname, SHMNAME_MAX);
  282.     shmtime = timestamp;
  283.     shmdate = datestamp;
  284.     return 0;
  285. }
  286.  
  287. static long
  288. shm_opendir(dirh, flags)
  289.     DIR *dirh;
  290.     int flags;
  291. {
  292.     dirh->index = 0;
  293.     return 0;
  294. }
  295.  
  296. static long
  297. shm_readdir(dirh, name, namelen, fc)
  298.     DIR *dirh;
  299.     char *name;
  300.     int namelen;
  301.     fcookie *fc;
  302. {
  303.     int i;
  304.     int giveindex = (dirh->flags == 0);
  305.     SHMFILE *s;
  306.  
  307.     s = shmroot;
  308.     i = dirh->index++;
  309.     while (i > 0 && s != 0) {
  310.         s = s->next;
  311.         --i;
  312.     }
  313.     if (!s)
  314.         return ENMFIL;
  315.  
  316.     fc->index = (long)s;
  317.     fc->fs = &shm_filesys;
  318.     fc->dev = SHMDEVICE;
  319.  
  320.     if (giveindex) {
  321.         namelen -= sizeof(long);
  322.         if (namelen <= 0) return ERANGE;
  323.         *((long *)name) = (long)s;
  324.         name += sizeof(long);
  325.     }
  326.     if (namelen < strlen(s->filename))
  327.         return ENAMETOOLONG;
  328.     strcpy(name, s->filename);
  329.     return 0;
  330. }
  331.  
  332. static long
  333. shm_rewinddir(dirh)
  334.     DIR *dirh;
  335. {
  336.     dirh->index = 0;
  337.     return 0;
  338. }
  339.  
  340. static long
  341. shm_closedir(dirh)
  342.     DIR *dirh;
  343. {
  344.     return 0;
  345. }
  346.  
  347. static long
  348. shm_pathconf(dir, which)
  349.     fcookie *dir;
  350.     int which;
  351. {
  352.     switch(which) {
  353.     case -1:
  354.         return DP_MAXREQ;
  355.     case DP_IOPEN:
  356.         return UNLIMITED;    /* no internal limit on open files */
  357.     case DP_MAXLINKS:
  358.         return 1;        /* we don't have hard links */
  359.     case DP_PATHMAX:
  360.         return PATH_MAX;    /* max. path length */
  361.     case DP_NAMEMAX:
  362.         return SHMNAME_MAX;    /* max. length of individual name */
  363.     case DP_ATOMIC:
  364.         return UNLIMITED;    /* all writes are atomic */
  365.     case DP_TRUNC:
  366.         return DP_AUTOTRUNC;    /* file names are truncated */
  367.     case DP_CASE:
  368.         return DP_CASEINSENS;    /* case preserved, but ignored */
  369.     default:
  370.         return EINVFN;
  371.     }
  372. }
  373.  
  374. static long
  375. shm_dfree(dir, buf)
  376.     fcookie *dir;
  377.     long *buf;
  378. {
  379.     long size;
  380. /* "sector" size is the size of the smallest amount of memory that can be
  381.    allocated. see mem.h for the definition of ROUND
  382.  */
  383.     long secsiz = ROUND(1);
  384.  
  385.     size = tot_rsize(core, 0) + tot_rsize(alt, 0);
  386.     *buf++ = size/secsiz;            /* number of free clusters */
  387.     size = tot_rsize(core, 1) + tot_rsize(alt, 1);
  388.     *buf++ = size/secsiz;            /* total number of clusters */
  389.     *buf++ = secsiz;            /* sector size (bytes) */
  390.     *buf++ = 1;                /* cluster size (in sectors) */
  391.     return 0;
  392. }
  393.  
  394. static DEVDRV *
  395. shm_getdev(fc, devsp)
  396.     fcookie *fc;
  397.     long *devsp;
  398. {
  399.     SHMFILE *s;
  400.  
  401.     s = (SHMFILE *)fc->index;
  402.  
  403.     *devsp = (long)s;
  404.     return &shm_device;
  405. }
  406.  
  407. /*
  408.  * create a shared memory region
  409.  */
  410.  
  411. static long
  412. shm_creat(dir, name, mode, attrib, fc)
  413.     fcookie *dir;
  414.     const char *name;
  415.     unsigned mode;
  416.     int attrib;
  417.     fcookie *fc;
  418. {
  419.     SHMFILE *s;
  420.  
  421. /*
  422.  * see if the name already exists
  423.  */
  424.     for (s = shmroot; s; s = s->next) {
  425.         if (!stricmp(s->filename, name)) {
  426.             DEBUG("shm_creat: file exists");
  427.             return EACCDN;
  428.         }
  429.     }
  430.  
  431.     s = (SHMFILE *)kmalloc(SIZEOF(SHMFILE));
  432.     if (!s)
  433.         return ENSMEM;
  434.  
  435.     s->inuse = 0;
  436.     strncpy(s->filename, name, SHMNAME_MAX);
  437.     s->filename[SHMNAME_MAX] = 0;
  438.     s->uid = curproc->ruid;
  439.     s->gid = curproc->rgid;
  440.     s->mode = mode;
  441.     s->next = shmroot;
  442.     s->reg = 0;
  443.     s->time = shmtime = timestamp;
  444.     s->date = shmdate = datestamp;
  445.     shmroot = s;
  446.  
  447.     fc->fs = &shm_filesys;
  448.     fc->index = (long)s;
  449.     fc->dev = dir->dev;
  450.  
  451.     return 0;
  452. }
  453.  
  454. /*
  455.  * Shared memory device driver
  456.  */
  457.  
  458. /*
  459.  * BUG: file locking and the O_SHMODE restrictions are not implemented
  460.  * for shared memory
  461.  */
  462.  
  463. static long
  464. shm_open(f)
  465.     FILEPTR *f;
  466. {
  467.     SHMFILE *s;
  468.  
  469.     s = (SHMFILE *)f->devinfo;
  470.     s->inuse++;
  471.     return 0;
  472. }
  473.  
  474. static long
  475. shm_write(f, buf, nbytes)
  476.     FILEPTR *f; const char *buf; long nbytes;
  477. {
  478.     SHMFILE *s;
  479.     char *where;
  480.     long bytes_written = 0;
  481.  
  482.     s = (SHMFILE *)f->devinfo;
  483.     if (!s->reg)
  484.         return 0;
  485.  
  486.     if (nbytes + f->pos > s->reg->len)
  487.         nbytes = s->reg->len - f->pos;
  488.  
  489.     where = (char *)s->reg->loc + f->pos;
  490.  
  491. /* BUG: memory read/writes should check for valid addresses */
  492.  
  493. TRACE("shm_write: %ld bytes to %lx", nbytes, where);
  494.  
  495.     while (nbytes-- > 0) {
  496.         *where++ = *buf++;
  497.         bytes_written++;
  498.     }
  499.     f->pos += bytes_written;
  500.     s->time = timestamp;
  501.     s->date = datestamp;
  502.     return bytes_written;
  503. }
  504.  
  505. static long
  506. shm_read(f, buf, nbytes)
  507.     FILEPTR *f; char *buf; long nbytes;
  508. {
  509.     SHMFILE *s;
  510.     char *where;
  511.     long bytes_read = 0;
  512.  
  513.     s = (SHMFILE *)f->devinfo;
  514.     if (!(s->reg))
  515.         return 0;
  516.  
  517.     if (nbytes + f->pos > s->reg->len)
  518.         nbytes = s->reg->len - f->pos;
  519.  
  520.     where = (char *)s->reg->loc + f->pos;
  521.  
  522. TRACE("shm_read: %ld bytes from %lx", nbytes, where);
  523.  
  524.     while (nbytes-- > 0) {
  525.         *buf++ = *where++;
  526.         bytes_read++;
  527.     }
  528.     f->pos += bytes_read;
  529.     return bytes_read;
  530. }
  531.  
  532. /*
  533.  * shm_ioctl: currently, the only IOCTL's available are:
  534.  * SHMSETBLK:  set the address of the shared memory file. This
  535.  *             call may only be made once per region, and then only
  536.  *           if the region is open for writing.
  537.  * SHMGETBLK:  get the address of the shared memory region. This
  538.  *             call fails (returns 0) if SHMSETBLK has not been
  539.  *             called yet for this shared memory file.
  540.  */
  541.  
  542. static long
  543. shm_ioctl(f, mode, buf)
  544.     FILEPTR *f; int mode; void *buf;
  545. {
  546.     SHMFILE *s;
  547.     MEMREGION *m;
  548.     int i;
  549.     long r;
  550.  
  551.     s = (SHMFILE *)f->devinfo;
  552.     switch(mode) {
  553.     case SHMSETBLK:
  554.         if (s->reg) {
  555.             DEBUG("Fcntl: SHMSETBLK already performed for %s",
  556.                 s->filename);
  557.             return ERANGE;
  558.         }
  559.         if ((f->flags & O_RWMODE) == O_RDONLY) {
  560.             DEBUG("Fcntl: SHMSETBLK: %s was opened read-only",
  561.                 s->filename);
  562.             return EACCDN;
  563.         }
  564.     /* find the memory region to be attached */
  565.         m = 0;
  566.         for (i = curproc->num_reg - 1; i >= 0; i--) {
  567.             if (curproc->addr[i] == (virtaddr)buf) {
  568.                 m = curproc->mem[i];
  569.                 break;
  570.             }
  571.         }
  572.         if (!m || !buf) {
  573.             DEBUG("Fcntl: SHMSETBLK: bad address %lx", buf);
  574.             return EIMBA;
  575.         }
  576.         m->links++;
  577.         s->reg = m;
  578.         return 0;
  579.     case SHMGETBLK:
  580.         if (!(m = s->reg)) {
  581.             DEBUG("Fcntl: no address for SHMGETBLK");
  582.             return 0;
  583.         }
  584.     /* check for memory limits */
  585.         if (curproc->maxmem) {
  586.             if (m->len > curproc->maxmem - memused(curproc)) {
  587.                 DEBUG("Fcntl: SHMGETBLK would violate memory limits");
  588.                 return 0;
  589.             }
  590.         }
  591.         return (long)attach_region(curproc, m);
  592.     case FIONREAD:
  593.     case FIONWRITE:
  594.         if (s->reg == 0) {
  595.             r = 0;
  596.         } else {
  597.             r = s->reg->len - f->pos;
  598.             if (r < 0) r = 0;
  599.         }
  600.         *((long *)buf) = r;
  601.         return 0;
  602.     default:
  603.         DEBUG("shmfs: bad Fcntl command");
  604.     }
  605.     return EINVFN;
  606. }
  607.  
  608. static long
  609. shm_lseek(f, where, whence)
  610.     FILEPTR *f; long where; int whence;
  611. {
  612.     long newpos = 0, maxpos;
  613.     SHMFILE *s;
  614.  
  615.     s = (SHMFILE *)f->devinfo;
  616.  
  617.     if (s->reg)
  618.         maxpos = s->reg->len;
  619.     else
  620.         maxpos = 0;
  621.  
  622.     switch(whence) {
  623.     case 0:
  624.         newpos = where;
  625.         break;
  626.     case 1:
  627.         newpos = f->pos + where;
  628.         break;
  629.     case 2:
  630.         newpos = maxpos - where;
  631.         break;
  632.     default:
  633.         return EINVFN;
  634.     }
  635.  
  636.     if (newpos < 0 || newpos > maxpos)
  637.         return ERANGE;
  638.  
  639.     f->pos = newpos;
  640.     return newpos;
  641. }
  642.  
  643. static long
  644. shm_datime(f, timeptr, rwflag)
  645.     FILEPTR *f;
  646.     short *timeptr;
  647.     int rwflag;
  648. {
  649.     SHMFILE *s;
  650.  
  651.     s = (SHMFILE *)f->devinfo;
  652.     if (rwflag) {
  653.         s->time = *timeptr++;
  654.         s->date = *timeptr;
  655.     } else {
  656.         *timeptr++ = s->time;
  657.         *timeptr++ = s->date;
  658.     }
  659.     return 0;
  660. }
  661.  
  662. static long
  663. shm_close(f, pid)
  664.     FILEPTR *f;
  665.     int pid;
  666. {
  667.     SHMFILE *s;
  668.  
  669.     if (f->links <= 0) {
  670.         s = (SHMFILE *)f->devinfo;
  671.         s->inuse--;
  672.     }
  673.     return 0;
  674. }
  675.  
  676.