home *** CD-ROM | disk | FTP | other *** search
/ GEMini Atari / GEMini_Atari_CD-ROM_Walnut_Creek_December_1993.iso / files / mint / ramfs / ramfs.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-08-03  |  23.5 KB  |  1,008 lines

  1. /*
  2.  * 'Ramfs': a (resizable) ramdisk file system
  3.  * by Thierry Bousch
  4.  *
  5.  * We make the standing assumption that sizeof(int)==2, that all functions
  6.  * pass their arguments on the stack, and that d0-d1/a0-a1 are the only
  7.  * scratch registers. Oh well, you need an ANSI compiler too...
  8.  *
  9.  * Version: 1.1 (may 93)
  10.  * Revision history:
  11.  * 1.0    Added version number, and macro-ized TRACE so that it is possible
  12.  *    to compile with or without debug information.
  13.  * 1.1  Added setuid, setgid and sticky bit for directories. Macro-ized
  14.  *      also DEBUG, ALERT and FATAL.
  15.  */
  16.  
  17. #include <string.h>
  18. #include "atarierr.h"
  19. #include "filesys.h"
  20.  
  21. #define VERSION  "1.1"
  22.  
  23. /* 
  24.  * You may edit the following constants:
  25.  *
  26.  *    RAMDRV        drive identifier (here R:)
  27.  *    RAMFILE_MAX    maximum length of a filename
  28.  *    BLKSIZE        chunk size (must be a power of two)
  29.  *
  30.  * Define the symbols NO_{TRACE,DEBUG,ALERT,FATAL} to disable trace,
  31.  * debug, alert and fatal calls, respectively.
  32.  */
  33.  
  34. #define RAMDRV        ('R'-'A')
  35. #define RAMFILE_MAX    29
  36. #define BLKSIZE        512L
  37. #define NO_TRACE
  38.  
  39. /*
  40.  * this points to the structure that has all the useful functions that
  41.  * the kernel told us about
  42.  */
  43.  
  44. struct kerinfo *kernel;
  45.  
  46. #define CCONWS        (void)(*kernel->dos_tab[0x09])
  47. #define RWABS        (*kernel->bios_tab[4])
  48. #define GETBPB        (void *)(*kernel->bios_tab[7])
  49.  
  50. #define Timestamp    (*kernel->dos_tab[0x2c])
  51. #define Datestamp     (*kernel->dos_tab[0x2a])
  52. #define Domain()    (*kernel->dos_tab[0x119])(-1)
  53. #define FreeMemory()    (*kernel->dos_tab[0x48])(-1L)
  54. #define Getpid        (*kernel->dos_tab[0x10b])
  55. #define Getuid        (*kernel->dos_tab[0x10f])
  56. #define Getgid        (*kernel->dos_tab[0x114])
  57. #define Geteuid        (*kernel->dos_tab[0x138])
  58. #define Getegid        (*kernel->dos_tab[0x139])
  59.  
  60. #define Kmalloc        (*kernel->kmalloc)
  61. #define Kfree        (*kernel->kfree)
  62. #define Stricmp        (*kernel->stricmp)
  63. #define Strlwr        (*kernel->strlwr)
  64. #define Unixtime    (*kernel->unixtim)
  65. #define Dostime        (*kernel->dostim)
  66. #define Denyshare    (*kernel->denyshare)
  67. #define Denylock    (*kernel->denylock)
  68.  
  69. #ifndef NULL
  70. # define NULL    ((void *)0L)
  71. #endif
  72.  
  73. /* Useful macros */
  74.  
  75. #define IS_DIRECTORY(s)    (((s)->mode & S_IFMT) == S_IFDIR)
  76. #define IS_SYMLINK(s)    (((s)->mode & S_IFMT) == S_IFLNK)
  77. #define IS_SETUID(s)    ((s)->mode & S_ISUID)
  78. #define IS_SETGID(s)    ((s)->mode & S_ISGID)
  79. #define IS_STICKY(s)    ((s)->mode & S_ISVTX)
  80.  
  81. /* Conditional debugging */
  82.  
  83. #ifdef NO_DEBUG
  84. # define DEBUG(x)
  85. #else
  86. # define DEBUG(x)    (*kernel->debug)x
  87. #endif
  88.  
  89. #ifdef NO_ALERT
  90. # define ALERT(x)
  91. #else
  92. # define ALERT(x)    (*kernel->alert)x
  93. #endif
  94.  
  95. #ifdef NO_TRACE
  96. # define TRACE(x)
  97. #else
  98. # define TRACE(x)    (*kernel->trace)x
  99. #endif
  100.  
  101. #ifdef NO_FATAL
  102. # define FATAL(x)
  103. #else
  104. # define FATAL(x)    (*kernel->fatal)x
  105. #endif
  106.  
  107. /* Forward declarations of the file system functions */
  108.  
  109. long    ram_root    (int drv, fcookie *fc);
  110. long    ram_lookup    (fcookie *dir, char *name, fcookie *fc);
  111. long    ram_creat    (fcookie *dir, char *name, unsigned mode,
  112.                 int attrib, fcookie *fc);
  113. DEVDRV*    ram_getdev    (fcookie *fc, long *devsp);
  114. long    ram_getxattr    (fcookie *fc, XATTR *xattr);
  115. long    ram_chattr    (fcookie *fc, int attrib);
  116. long    ram_chown    (fcookie *fc, int uid, int gid);
  117. long    ram_chmode    (fcookie *fc, unsigned mode);
  118. long    ram_mkdir    (fcookie *fc, char *name, unsigned mode);
  119. long    ram_rmdir    (fcookie *dir, char *name);
  120. long    ram_remove    (fcookie *dir, char *name);
  121. long    ram_getname    (fcookie *root, fcookie *dir, char *pathname);
  122. long    ram_rename    (fcookie *olddir, char *oldname,
  123.                 fcookie *newdir, char *newname);
  124. long    ram_opendir    (DIR *dirh, int flags);
  125. long    ram_readdir    (DIR *dirh, char *nm, int nmlen, fcookie *fc);
  126. long    ram_rewinddir    (DIR *dirh);
  127. long    ram_closedir     (DIR *dirh);
  128. long    ram_pathconf     (fcookie *dir, int which);
  129. long    ram_dfree    (fcookie *dir, long *buf);
  130. long    ram_writelabel    (fcookie *dir, char *name);
  131. long    ram_readlabel    (fcookie *dir, char *name, int namelen);
  132. long    ram_symlink    (fcookie *dir, char *name, char *to);
  133. long    ram_readlink    (fcookie *dir, char *buf, int len);
  134. long    ram_hardlink    (fcookie *fromdir, char *fromname,
  135.                 fcookie *todir, char *toname);
  136. long    ram_fscntl    (fcookie *dir, char *name, int cmd, long arg);
  137. long    ram_dskchng    (int drv);
  138.  
  139. /* Forward declarations of the device driver functions */
  140.  
  141. long    ram_open    (FILEPTR *f);
  142. long    ram_write    (FILEPTR *f, char *buf, long bytes);
  143. long    ram_read    (FILEPTR *f, char *buf, long bytes);
  144. long    ram_lseek    (FILEPTR *f, long where, int whence);
  145. long    ram_ioctl    (FILEPTR *f, int mode, void *buf);
  146. long    ram_datime    (FILEPTR *f, int *time, int rwflag);
  147. long    ram_close    (FILEPTR *f, int pid);
  148. long    ram_select    (FILEPTR *f, long p, int mode);
  149. void    ram_unselect    (FILEPTR *f, long p, int mode);
  150.  
  151. /* 
  152.  * Here is the structure used for ram files. The "next" field points to
  153.  * the following file/dir in that directory. The "up" field points to the 
  154.  * directory the file/dir is in, or NULL for the root directory. The
  155.  * "down" field is only used by subdirectories and points to the first
  156.  * entry in that subdirectory. "lst" is the list of open FILEPTRs for
  157.  * this file. "length" is the actual length, "data" the actual data, and
  158.  * "avail" is the length of the ram block allocated for "data".
  159.  * The field "unlink" is non-null only when the file is marked as deleted
  160.  * and must be removed on close.
  161.  *
  162.  * Note that all the memory is allocated in one block: it may cause trouble
  163.  * with big files if the memory is fragmented.
  164.  */
  165.  
  166. typedef struct ramfile {
  167.     struct ramfile *next, *up, *down;
  168.     char filename[RAMFILE_MAX+1];
  169.     int uid, gid, unlink;
  170.     short time, date;
  171.     unsigned mode;
  172.     FILEPTR *lst;
  173.     long length, avail;
  174.     char *data;
  175. } RAMFILE;
  176.  
  177. RAMFILE ramroot;
  178.  
  179. DEVDRV ram_device = {
  180.     ram_open, ram_write, ram_read, ram_lseek, ram_ioctl, ram_datime,
  181.     ram_close, ram_select, ram_unselect
  182. };
  183.  
  184. FILESYS ram_filesys = {
  185.     (FILESYS *)0,
  186.     0,
  187.     ram_root,
  188.     ram_lookup, ram_creat, ram_getdev, ram_getxattr,
  189.     ram_chattr, ram_chown, ram_chmode,
  190.     ram_mkdir, ram_rmdir, ram_remove, ram_getname, ram_rename,
  191.     ram_opendir, ram_readdir, ram_rewinddir, ram_closedir,
  192.     ram_pathconf, ram_dfree,
  193.     ram_writelabel, ram_readlabel, ram_symlink, ram_readlink,
  194.     ram_hardlink, ram_fscntl, ram_dskchng
  195. };
  196.  
  197. #define DRIVE_MAP    *(unsigned long *)(0x4c2L)
  198.  
  199. /*
  200.  * This function is called by the kernel when the
  201.  * file system is being loaded, and should return the file system
  202.  * structure
  203.  */
  204.  
  205. FILESYS *ram_init (struct kerinfo *k)
  206. {
  207.     kernel = k;
  208.  
  209.     CCONWS("Ramdisk filesystem for MiNT (Version " VERSION ", compiled " 
  210.     __DATE__ ") by T.Bousch\r\n");
  211.  
  212.     /* Add drive 'R' to the list of Bios drives */
  213.     DRIVE_MAP |= (1UL << RAMDRV);
  214.  
  215.     TRACE(("ram_init: initialize filesystem"));
  216.  
  217.     ramroot.next = ramroot.up = ramroot.down = NULL;
  218.     ramroot.unlink = 0;
  219.     ramroot.filename[0] = 0;
  220.     ramroot.uid  = ramroot.gid = 0;
  221.     ramroot.time = Timestamp();
  222.     ramroot.date = Datestamp();
  223.     ramroot.mode = S_IFDIR | DEFAULT_DIRMODE;
  224.     ramroot.lst  = NULL;
  225.     ramroot.length = ramroot.avail = 0L;
  226.     ramroot.data = NULL;
  227.  
  228.     return &ram_filesys;
  229. }
  230.  
  231. long ram_root (int drv, fcookie *fc)
  232. {
  233.     if ((unsigned)drv == RAMDRV) {
  234.         TRACE(("ram_root: drive %c: is a ramdisk", 'A' + RAMDRV));
  235.         fc->fs = &ram_filesys;
  236.         fc->dev = drv;
  237.         fc->index = (long) &ramroot;
  238.         return 0;
  239.     } else {
  240.         fc->fs = NULL;    /* Not our drive */
  241.         return EDRIVE;
  242.     }
  243. }
  244.  
  245. long ram_lookup (fcookie *dir, char *name, fcookie *fc)
  246. {
  247.     RAMFILE *s, *d;
  248.     
  249.     TRACE(("ram_lookup: search name [%s]", name));
  250.  
  251.     d = (RAMFILE *)dir->index;
  252.     
  253.     if (!d || !IS_DIRECTORY(d)) {
  254.         DEBUG(("ram_lookup: bad directory"));
  255.         return EPTHNF;
  256.     }
  257.     /* Empty name and "." are the directory itself */
  258.     if (!*name || !Stricmp(name, ".")) {
  259.         *fc = *dir;
  260.         return 0;
  261.     }
  262.     /* ".." could be a mount point */
  263.     if (!Stricmp(name, "..")) {
  264.         s = d->up;
  265.         if (s) {
  266.             fc->index = (long)s;
  267.             fc->fs = &ram_filesys;
  268.             fc->dev = RAMDRV;
  269.             return 0;
  270.         } else {
  271.             *fc = *dir;
  272.             return EMOUNT;
  273.         }
  274.     }
  275.     
  276.     for (s = d->down; s; s = s->next) {
  277.         if (!Stricmp(s->filename,name))
  278.             break;
  279.     }    
  280.  
  281.     if (!s) {
  282.         DEBUG(("ram_lookup: name [%s] not found", name));
  283.         return EFILNF;
  284.     } else {
  285.         fc->index = (long)s;
  286.         fc->fs = &ram_filesys;
  287.         fc->dev = RAMDRV;
  288.     }
  289.     return 0;
  290. }
  291.  
  292. long ram_getxattr (fcookie *fc, XATTR *xattr)
  293. {
  294.     RAMFILE *s;
  295.     
  296.     TRACE(("ram_getxattr: get file attributes"));
  297.     
  298.     xattr->blksize = BLKSIZE;
  299.     xattr->dev = RAMDRV;
  300.     xattr->nlink = 1;
  301.     s = (RAMFILE *)fc->index;
  302.     xattr->index = (long)s;
  303.     xattr->uid = s->uid; xattr->gid = s->gid;
  304.     xattr->size = s->length;
  305.         xattr->nblocks = (s->avail + BLKSIZE - 1) / BLKSIZE;
  306.     xattr->mtime = xattr->ctime = xattr->atime = s->time;
  307.     xattr->mdate = xattr->cdate = xattr->adate = s->date;
  308.     xattr->mode = s->mode;
  309.     xattr->attr = ((s->mode & (S_IWUSR|S_IWGRP|S_IWOTH)) ? 0 : FA_RDONLY)
  310.             | (IS_DIRECTORY(s) ? FA_DIR : 0);
  311.     return 0;
  312. }
  313.  
  314. long ram_chattr (fcookie *fc, int attrib)
  315. {
  316.     RAMFILE *s;
  317.     
  318.     TRACE(("ram_chattr: new attrib 0%o", attrib));
  319.  
  320.     s = (RAMFILE *)fc->index;
  321.     if (attrib & FA_RDONLY) {
  322.         s->mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
  323.     } else if ( !(s->mode & (S_IWUSR|S_IWGRP|S_IWOTH)) ) {
  324.         s->mode |= (S_IWUSR|S_IWGRP|S_IWOTH);
  325.     }
  326.     return 0;
  327. }
  328.  
  329. long ram_chown (fcookie *fc, int uid, int gid)
  330. {
  331.     RAMFILE *s;
  332.     
  333.     TRACE(("ram_chown: new owner is %d.%d", uid, gid));
  334.  
  335.     s = (RAMFILE *)fc->index;
  336.     s->uid = uid;
  337.     s->gid = gid;
  338.     return 0;
  339. }
  340.  
  341. long ram_chmode (fcookie *fc, unsigned mode)
  342. {
  343.     RAMFILE *s;
  344.     
  345.     TRACE(("ram_chmode: new mode 0%o", mode));
  346.  
  347.     s = (RAMFILE *)fc->index;
  348.     s->mode = (s->mode & S_IFMT) | (mode & ~S_IFMT);
  349.     return 0;
  350. }
  351.  
  352. /*
  353.  * This routine removes a file or directory marked as deleted if
  354.  * nobody needs it anymore
  355.  */
  356.  
  357. static void unlink (RAMFILE *s)
  358. {
  359.     RAMFILE *d, *t, **old;
  360.  
  361.     if (s->lst == NULL && s->unlink != 0) {
  362.         d = s->up;
  363.         old = &d->down;
  364.         for (t = d->down; t && t != s; t = t->next)
  365.             old = &t->next;
  366.         if (!t) {
  367.             ALERT(("ram_unlink: file not found"));
  368.             return;
  369.         }
  370.         *old = s->next;
  371.         Kfree(s->data);
  372.         Kfree(s);
  373.         d->time = Timestamp();
  374.         d->date = Datestamp();
  375.     }
  376. }
  377.          
  378. long ram_remove (fcookie *dir, char *name)
  379. {
  380.     RAMFILE *d, *s;
  381.     
  382.     TRACE(("ram_remove: delete file [%s]", name));
  383.  
  384.     d = (RAMFILE *)dir->index;
  385.     for (s = d->down; s; s = s->next) {
  386.         if (!Stricmp(s->filename, name))
  387.             break;
  388.     }
  389.     if (!s) {
  390.         DEBUG(("ram_remove: file [%s] not found", name));
  391.         return EFILNF;
  392.     }
  393.     if (IS_DIRECTORY(s)) {
  394.         DEBUG(("ram_remove: [%s] is a directory", name));
  395.         return EACCDN;
  396.     }
  397.     /* If d is sticky, check that we own the file */
  398.     if (IS_STICKY(d) && Geteuid() && s->uid != Getuid()) {
  399.         DEBUG(("ram_remove: not owner"));
  400.         return EACCDN;
  401.     }
  402.     s->unlink++;
  403.     unlink(s);    
  404.     return 0;
  405. }
  406.  
  407. long ram_getname (fcookie *root, fcookie *dir, char *pathname)
  408. {
  409.     RAMFILE *s, *d;
  410.     char buf[PATH_MAX];
  411.  
  412.     *pathname = 0;    /* empty string */
  413.     d = (RAMFILE *)root->index;
  414.     s = (RAMFILE *)dir->index;
  415.     while (s) {
  416.         if (s == d) {
  417.             TRACE(("ram_getname: returned [%s]", pathname));
  418.             return 0;
  419.         }
  420.         strcpy(buf, "\\");
  421.         strcat(buf, s->filename);
  422.         strcat(buf, pathname);
  423.         strcpy(pathname, buf);
  424.         s = s->up;
  425.     }
  426.     DEBUG(("ram_getname: path not found"));
  427.     return EPTHNF;    /* not found */
  428. }
  429.  
  430. long ram_rename (fcookie *olddir, char *oldname,
  431.             fcookie *newdir, char *newname)
  432. {
  433.     RAMFILE *s, *d, *dold, *dnew, **old;
  434.     
  435.     TRACE(("ram_rename: mv %s %s", oldname, newname));
  436.  
  437.     /* Verify that "newname" doesn't exist */
  438.     dnew = (RAMFILE *)newdir->index;
  439.     for (s = dnew->down; s; s = s->next)
  440.         if (!Stricmp(s->filename, newname)) {
  441.             DEBUG(("ram_rename: file already exists"));
  442.             return EACCDN;
  443.         }
  444.     /* Verify that "oldname" exists */
  445.     dold = (RAMFILE *)olddir->index;
  446.     old = &dold->down;
  447.     for (s = dold->down; s; s = s->next)
  448.         if (!Stricmp(s->filename, oldname))
  449.             break;
  450.         else    old = &s->next;
  451.     if (!s) {
  452.         DEBUG(("ram_rename: file not found"));
  453.         return EFILNF;
  454.     }
  455.     /* Verify that "newdir" is not a subdirectory of "name" */
  456.     for (d = dnew; d; d = d->up)
  457.         if (d == s) {
  458.             DEBUG(("ram_rename: invalid move"));
  459.             return EACCDN;
  460.         }
  461.     strncpy(s->filename, newname, RAMFILE_MAX);
  462.     s->filename[RAMFILE_MAX] = 0;
  463.     if (dold != dnew) {
  464.         /* Rename across directories */
  465.         TRACE(("ram_rename: move across directories"));
  466.         *old = s->next;
  467.         s->next = dnew->down;
  468.         dnew->down = s;
  469.         s->up = dnew;
  470.     }
  471.     dold->time = dnew->time = Timestamp();
  472.     dold->date = dnew->date = Datestamp();
  473.  
  474.     return 0;
  475. }
  476.  
  477. long ram_opendir (DIR *dirh, int flags)
  478. {
  479.     RAMFILE *d;
  480.     
  481.     TRACE(("ram_opendir: open directory"));
  482.  
  483.     dirh->index = 0;
  484.     d = (RAMFILE *)dirh->fc.index;
  485.     *(RAMFILE **)(&dirh->fsstuff) = d->down;    /* next file */
  486.  
  487.     return 0;
  488. }
  489.  
  490. long ram_rewinddir (DIR *dirh)
  491. {
  492.     RAMFILE *d;
  493.     
  494.     TRACE(("ram_rewinddir: rewind directory"));
  495.  
  496.     dirh->index = 0;
  497.     d = (RAMFILE *)dirh->fc.index;
  498.     *(RAMFILE **)(&dirh->fsstuff) = d->down;    /* next file */
  499.  
  500.     return 0;
  501.  
  502. }
  503.  
  504. long ram_closedir (DIR *dirh)
  505. {
  506.     TRACE(("ram_closedir: close directory"));
  507.  
  508.     return 0;
  509. }
  510.  
  511. long ram_readdir (DIR *dirh, char *name, int namelen, fcookie *fc)
  512. {
  513.     int i;
  514.     int giveindex = (dirh->flags == 0);
  515.     RAMFILE *s;
  516.     char *Filename;
  517.     
  518.     i = dirh->index++;
  519.     s = (RAMFILE *)dirh->fc.index;    /* Current directory */
  520.     if (i == 0) {
  521.         /* The "." entry is the first one */
  522.         Filename = ".";
  523.     } else if (i == 1 && s->up != NULL) {
  524.         /* The ".." entry is the second one */
  525.         s = s->up;
  526.         Filename = "..";
  527.     } else {
  528.         /* Any regular entry */
  529.         s = *(RAMFILE **)(&dirh->fsstuff);
  530.         if (!s) {
  531.             TRACE(("ram_readdir: no more files"));
  532.             return ENMFIL;
  533.         }
  534.         *(RAMFILE **)(&dirh->fsstuff) = s->next;
  535.         Filename = s->filename;
  536.     }
  537.     TRACE(("ram_readdir: entry %d: %s", i, Filename));
  538.     
  539.     fc->index = (long)s;
  540.     fc->fs = &ram_filesys;
  541.     fc->dev = RAMDRV;
  542.     
  543.     if (giveindex) {
  544.         namelen -= (int)sizeof(long);
  545.         if (namelen <= 0) return ERANGE;
  546.         *((long *)name) = (long)s;
  547.         name += sizeof(long);
  548.     }
  549.     if (namelen <= strlen(Filename)) {
  550.         DEBUG(("ram_readdir: name too long"));
  551.         return ENAMETOOLONG;
  552.     }
  553.     strcpy(name, Filename);
  554.     return 0;
  555. }
  556.     
  557. long ram_pathconf (fcookie *dir, int which)
  558. {
  559.     TRACE(("ram_pathconf: limit %d", which));
  560.  
  561.     switch(which) {
  562.     case -1:
  563.         return DP_MAXREQ;
  564.     case DP_IOPEN:
  565.         return UNLIMITED;    /* no internal limit on open files */
  566.     case DP_MAXLINKS:
  567.         return 1;        /* we don't have hard links */
  568.     case DP_PATHMAX:
  569.         return PATH_MAX;    /* max. path length */
  570.     case DP_NAMEMAX:
  571.         return RAMFILE_MAX;    /* max. length of individual name */
  572.     case DP_ATOMIC:
  573.         return UNLIMITED;    /* all writes are atomic */
  574.     case DP_TRUNC:
  575.         return DP_AUTOTRUNC;    /* file names are truncated */
  576.     default:
  577.         DEBUG(("ram_pathconf: invalid parameter"));
  578.         return EINVFN;
  579.     }
  580. }
  581.  
  582. /*
  583.  * The following (recursive) function calculates the total size of a
  584.  * file or directory
  585.  */
  586.  
  587. static long mem_used (RAMFILE *d)
  588. {
  589.     long used = 0L;
  590.     RAMFILE *s;
  591.     
  592.     if (!IS_DIRECTORY(d))
  593.         return d->avail;
  594.     /* If it's not a regular file or a symbolic link, then */
  595.     for (s = d->down; s; s = s->next)
  596.         used += mem_used(s);
  597.     return used;
  598. }
  599.  
  600. long ram_dfree (fcookie *dir, long *buf)
  601. {
  602.     long memfree, memused;
  603.     
  604.     TRACE(("ram_dfree: getting free disk space"));
  605.  
  606.     memfree = FreeMemory();
  607.     memused = mem_used(&ramroot);
  608.  
  609.     *buf++ = memfree / BLKSIZE;        /* free blocks        */
  610.     *buf++ = (memfree + memused) / BLKSIZE;    /* total nb of blocks */
  611.     *buf++ = BLKSIZE;            /* sector size        */
  612.     *buf   = 1;                /* 1 sector per block */
  613.     
  614.     return 0;
  615. }
  616.  
  617. long ram_writelabel (fcookie *dir, char *name)
  618. {
  619.     DEBUG(("ram_writelabel: not implemented"));
  620.     return EINVFN;
  621. }
  622.  
  623. long ram_readlabel (fcookie *dir, char *name, int namelen)
  624. {
  625.     DEBUG(("ram_readlabel: not implemented"));
  626.     return EINVFN;
  627. }
  628.  
  629. long ram_hardlink (fcookie *fromdir, char *fromname,
  630.             fcookie *todir, char *toname)
  631. {
  632.     DEBUG(("ram_hardlink: invalid function"));
  633.     return EINVFN;
  634. }
  635.  
  636. long ram_fscntl (fcookie *dir, char *name, int cmd, long arg)
  637. {
  638.     DEBUG(("ram_fscntl: nothing available"));
  639.     return EINVFN;    /* Nothing for now */
  640. }
  641.  
  642. long ram_dskchng (int drv)
  643. {
  644.     TRACE(("ram_dskchng: ram disk changed ?"));
  645.     return 0;    /* No media change on a ram disk! */
  646. }
  647.  
  648. DEVDRV *ram_getdev (fcookie *fc, long *devsp)
  649. {
  650.     RAMFILE *s;
  651.     
  652.     TRACE(("ram_getdev: find device driver"));
  653.  
  654.     s = (RAMFILE *)fc->index;
  655.     *devsp = (long)s;
  656.     return &ram_device;
  657. }
  658.  
  659. /*
  660.  * Create a ram file. This function is used for regular files _and_
  661.  * directories
  662.  */
  663.  
  664. static long 
  665. create_ram_file (fcookie *dir, char *name, unsigned mode, fcookie *fc)
  666. {
  667.     RAMFILE *s, *d;
  668.  
  669.     TRACE(("create_ram_file: file [%s] mode 0%o", name, mode));
  670.     
  671.     /* Does this name already exist ? */
  672.     d = (RAMFILE *)dir->index;
  673.     for (s = d->down; s; s = s->next) {
  674.         if (!Stricmp(s->filename, name)) {
  675.             DEBUG(("create_ram_file: file exists"));
  676.             return EACCDN;
  677.         }
  678.     }
  679.     /* The names "", "." and ".." are reserved */
  680.     if (!*name || !Stricmp(name, ".") || !Stricmp(name, "..")) {
  681.         DEBUG(("create_ram_file: invalid filename"));
  682.         return EACCDN;
  683.     }
  684.     s = (RAMFILE *)Kmalloc(sizeof(RAMFILE));
  685.     if (!s) {
  686.         ALERT(("create_ram_file: out of memory"));
  687.         return ENSMEM;
  688.     }
  689.     strncpy(s->filename, name, RAMFILE_MAX);
  690.     s->filename[RAMFILE_MAX] = 0;
  691.     /*
  692.      * If the directory has the bits Setuid or Setgid set, then the
  693.      * file inherits the uid or gid of its parent:
  694.      */
  695.     s->uid = IS_SETUID(d) ? d->uid : Getuid();
  696.     s->gid = IS_SETGID(d) ? d->gid : Getgid();
  697.     s->mode = mode;
  698.     s->lst  = NULL;
  699.     s->length = s->avail = 0L;
  700.     s->data = NULL;
  701.     s->time = d->time = Timestamp();
  702.     s->date = d->date = Datestamp();
  703.     s->next = d->down;
  704.     d->down = s;
  705.     s->down = NULL;
  706.     s->up   = d;
  707.     s->unlink = 0;
  708.     
  709.     fc->fs = &ram_filesys;
  710.     fc->index = (long)s;
  711.     fc->dev = dir->dev;
  712.     
  713.     return 0;
  714. }
  715.  
  716. long ram_creat (fcookie *dir, char *name, unsigned mode,
  717.             int attrib, fcookie *fc)
  718. {
  719.     TRACE(("ram_creat: create regular file"));
  720.     
  721.     return create_ram_file (dir, name, mode|S_IFREG, fc);
  722. }
  723.  
  724. long ram_mkdir (fcookie *fc, char *name, unsigned mode)
  725. {
  726.     fcookie Dummy;
  727.     
  728.     TRACE(("ram_mkdir: make directory"));
  729.  
  730.     return create_ram_file (fc, name, mode|S_IFDIR, &Dummy);
  731. }
  732.  
  733. long ram_rmdir (fcookie *dir, char *name)
  734. {
  735.     RAMFILE *d, *s;
  736.     
  737.     TRACE(("ram_rmdir: remove directory [%s]", name));
  738.  
  739.     d = (RAMFILE *)dir->index;
  740.     for (s = d->down; s; s = s->next) {
  741.         if (!Stricmp(s->filename, name))
  742.             break;
  743.     }
  744.     if (!s) {
  745.         DEBUG(("ram_rmdir: directory [%s] not found", name));
  746.         return EFILNF;
  747.     }
  748.     if (!IS_DIRECTORY(s) && !IS_SYMLINK(s)) {
  749.         DEBUG(("ram_rmdir: [%s] isn't a directory", name));
  750.         return EACCDN;
  751.     }
  752.     if (IS_DIRECTORY(s) && s->down) {
  753.         DEBUG(("ram_rmdir: directory [%s] isn't empty", name));
  754.         return EACCDN;
  755.     }
  756.     /* If d is sticky, check that we own the subdirectory */
  757.     if (IS_STICKY(d) && Geteuid() && s->uid != Getuid()) {
  758.         DEBUG(("ram_rmdir: not owner"));
  759.         return EACCDN;
  760.     }
  761.     s->unlink++;
  762.     unlink(s);
  763.     return 0;
  764. }
  765.  
  766. long ram_symlink (fcookie *dir, char *name, char *to)
  767. {
  768.     RAMFILE *s;
  769.     fcookie Fc; 
  770.     long ret, len;
  771.  
  772.     TRACE(("ram_symlink: create symbolic link"));
  773.  
  774.     ret = create_ram_file (dir, name, 0777|S_IFLNK, &Fc);
  775.     if (ret == 0) {
  776.         s = (RAMFILE *)Fc.index;
  777.         len = strlen(to) + 1;
  778.         s->data = Kmalloc(len);
  779.         if (!s->data) {
  780.             ALERT(("ram_symlink: out of memory"));
  781.             s->unlink++;
  782.             unlink(s);
  783.             return ENSMEM;
  784.         }
  785.         s->length = s->avail = len;
  786.         strcpy(s->data, to);
  787.     }
  788.     return ret;
  789. }
  790.  
  791. long ram_readlink (fcookie *dir, char *buf, int len)
  792. {
  793.     RAMFILE *s;
  794.  
  795.     s = (RAMFILE *)dir->index;
  796.     if (!IS_SYMLINK(s)) {
  797.         DEBUG(("ram_readlink: not a symbolic link"));
  798.         return EACCDN;
  799.     }
  800.     if (s->length > len) {
  801.         DEBUG(("ram_readlink: name too long"));
  802.         return ENAMETOOLONG;
  803.     }
  804.     strcpy(buf, s->data);
  805.     TRACE(("ram_readlink: returned [%s]", buf));
  806.     return 0;
  807. }
  808.  
  809. /*
  810.  * The ram disk driver
  811.  */
  812.  
  813. static void enlarge_ramfile (RAMFILE *s, long new_size)
  814. {
  815.     char *data2;
  816.     long quantum;
  817.     
  818.     /* We choose bigger blocks for big files */
  819.     quantum = (new_size > 16*BLKSIZE ? 4 : 1) * BLKSIZE;
  820.     /* 
  821.      * Round to the next multiple of quantum; we assume that 
  822.      * quantum is a power of two !!
  823.      */
  824.     new_size = (new_size + quantum - 1) & ~(quantum - 1);
  825.     data2 = (char *)Kmalloc(new_size);
  826.     if (data2) {
  827.         bcopy(s->data, data2, s->length);
  828.         Kfree(s->data);
  829.         s->data = data2;
  830.         s->avail = new_size;
  831.     } else    ALERT(("enlarge_ramfile: out of memory"));
  832. }
  833.  
  834. long ram_open (FILEPTR *f)
  835. {
  836.     RAMFILE *s;
  837.  
  838.     TRACE(("ram_open: open file"));
  839.  
  840.     s = (RAMFILE *)f->devinfo;
  841.     /* Check the sharing mode */
  842.     if (Denyshare(s->lst, f)) {
  843.         DEBUG(("ram_open: sharing modes conflict"));
  844.         return EACCDN;
  845.     }
  846.     if (f->flags & O_TRUNC) {
  847.         /* truncate the file */
  848.         if (s->lst) {
  849.             /* Can it happen ? */
  850.             ALERT(("ram_open: O_TRUNC without O_EXCL"));
  851.             return EACCDN;
  852.         } else {
  853.             Kfree(s->data);
  854.             s->length = s->avail = 0L;
  855.             s->data = 0;
  856.         }
  857.     }
  858.     f->next = s->lst;
  859.     s->lst = f;
  860.     
  861.     return 0;
  862. }
  863.  
  864. long ram_close (FILEPTR *f, int pid)
  865. {
  866.     RAMFILE *s;
  867.     FILEPTR **old, *g;
  868.     
  869.     TRACE(("ram_close: close file"));
  870.  
  871.     if (f->links == 0) {
  872.         s = (RAMFILE *)f->devinfo;
  873.         old = &(s->lst);
  874.         for (g = s->lst; g; g = g->next) {
  875.             if (g == f)
  876.                 break;
  877.             old = &(g->next);
  878.         }
  879.         if (g == NULL)
  880.             ALERT(("ram_close: FILEPTR not found"));
  881.         else    *old = f->next;
  882.  
  883.         unlink(s);
  884.     }
  885.     return 0;
  886. }
  887.  
  888. long ram_write (FILEPTR *f, char *buf, long nbytes)
  889. {
  890.     RAMFILE *s;
  891.     long new_size;
  892.     
  893.     s = (RAMFILE *)f->devinfo;
  894.     new_size = nbytes + f->pos;
  895.     if (new_size > s->avail)
  896.         enlarge_ramfile(s, new_size);
  897.     /* Hope that the file is big enough now */
  898.     if (new_size > s->avail)
  899.         nbytes = s->avail - f->pos;
  900.     /* Copy the data */
  901.     TRACE(("ram_write: %ld bytes from pos %ld", nbytes, f->pos));
  902.     bcopy(buf, s->data + f->pos, nbytes);
  903.     /* Update the file status */
  904.     f->pos += nbytes;
  905.     if (f->pos > s->length)
  906.         s->length = f->pos;
  907.     s->time = Timestamp();
  908.     s->date = Datestamp();
  909.  
  910.     return nbytes;
  911. }
  912.         
  913. long ram_read (FILEPTR *f, char *buf, long nbytes)
  914. {
  915.     RAMFILE *s;
  916.  
  917.     s = (RAMFILE *)f->devinfo;
  918.     if (nbytes + f->pos > s->length)
  919.         nbytes = s->length - f->pos;
  920.     /* Copy the data */
  921.     TRACE(("ram_read: %ld bytes from pos %ld", nbytes, f->pos));
  922.     bcopy(s->data + f->pos, buf, nbytes);
  923.     f->pos += nbytes;
  924.     
  925.     return nbytes;
  926. }
  927.  
  928. /* File locking code not yet implemented */
  929.  
  930. long ram_ioctl (FILEPTR *f, int mode, void *buf)
  931. {
  932.     TRACE(("ram_ioctl: mode %d", mode));
  933.  
  934.     if (mode == FIONREAD || mode == FIONWRITE) {
  935.         *((long *)buf) = 1;
  936.         return 0;
  937.     }
  938.     else if (mode == F_SETLK || mode == F_GETLK) {
  939.         DEBUG(("ram_ioctl: locking not implemented"));
  940.         return EINVFN;
  941.     }
  942.     DEBUG(("ram_ioctl: invalid function"));
  943.     return EINVFN;
  944. }
  945.  
  946. long ram_lseek(FILEPTR *f, long where, int whence)
  947. {
  948.     RAMFILE *s;
  949.     long newpos;
  950.  
  951.     TRACE(("ram_lseek: goto %d, mode %d", where, whence));
  952.     
  953.     s = (RAMFILE *)f->devinfo;
  954.     
  955.     switch(whence) {
  956.     case 0:
  957.         newpos = where;
  958.         break;
  959.     case 1:
  960.         newpos = f->pos + where;
  961.         break;
  962.     case 2:
  963.         newpos = s->length - where;
  964.         break;
  965.     default:
  966.         DEBUG(("ram_lseek: invalid mode"));
  967.         return EINVFN;
  968.     }
  969.     
  970.     if (newpos < 0 || newpos > s->length) {
  971.         TRACE(("ram_lseek: out of range"));
  972.         return ERANGE;
  973.     }
  974.     f->pos = newpos;
  975.     return newpos;
  976. }
  977.  
  978. long ram_datime (FILEPTR *f, int *timeptr, int rwflag)
  979. {
  980.     RAMFILE *s;
  981.     
  982.     s = (RAMFILE *)f->devinfo;
  983.     if (rwflag) {
  984.         TRACE(("ram_datime: set time and date"));
  985.         s->time = *timeptr++;
  986.         s->date = *timeptr;
  987.     } else {
  988.         TRACE(("ram_datime: get time and date"));
  989.         *timeptr++ = s->time;
  990.         *timeptr   = s->date;
  991.     }
  992.     return 0;
  993. }
  994.  
  995. long ram_select (FILEPTR *f, long p, int mode)
  996. {
  997.     TRACE(("ram_select: always ready"));
  998.  
  999.     return 1;    /* We're always ready */
  1000. }
  1001.  
  1002. void ram_unselect (FILEPTR *f, long p, int mode)
  1003. {
  1004.     TRACE(("ram_unselect: nothing to do"));
  1005.     
  1006.     /* Nothing for us to do */
  1007. }
  1008.