home *** CD-ROM | disk | FTP | other *** search
- /*
- * 'Ramfs': a (resizable) ramdisk file system
- * by Thierry Bousch
- *
- * We make the standing assumption that sizeof(int)==2, that all functions
- * pass their arguments on the stack, and that d0-d1/a0-a1 are the only
- * scratch registers. Oh well, you need an ANSI compiler too...
- *
- * Version: 1.1 (may 93)
- * Revision history:
- * 1.0 Added version number, and macro-ized TRACE so that it is possible
- * to compile with or without debug information.
- * 1.1 Added setuid, setgid and sticky bit for directories. Macro-ized
- * also DEBUG, ALERT and FATAL.
- */
-
- #include <string.h>
- #include "atarierr.h"
- #include "filesys.h"
-
- #define VERSION "1.1"
-
- /*
- * You may edit the following constants:
- *
- * RAMDRV drive identifier (here R:)
- * RAMFILE_MAX maximum length of a filename
- * BLKSIZE chunk size (must be a power of two)
- *
- * Define the symbols NO_{TRACE,DEBUG,ALERT,FATAL} to disable trace,
- * debug, alert and fatal calls, respectively.
- */
-
- #define RAMDRV ('R'-'A')
- #define RAMFILE_MAX 29
- #define BLKSIZE 512L
- #define NO_TRACE
-
- /*
- * this points to the structure that has all the useful functions that
- * the kernel told us about
- */
-
- struct kerinfo *kernel;
-
- #define CCONWS (void)(*kernel->dos_tab[0x09])
- #define RWABS (*kernel->bios_tab[4])
- #define GETBPB (void *)(*kernel->bios_tab[7])
-
- #define Timestamp (*kernel->dos_tab[0x2c])
- #define Datestamp (*kernel->dos_tab[0x2a])
- #define Domain() (*kernel->dos_tab[0x119])(-1)
- #define FreeMemory() (*kernel->dos_tab[0x48])(-1L)
- #define Getpid (*kernel->dos_tab[0x10b])
- #define Getuid (*kernel->dos_tab[0x10f])
- #define Getgid (*kernel->dos_tab[0x114])
- #define Geteuid (*kernel->dos_tab[0x138])
- #define Getegid (*kernel->dos_tab[0x139])
-
- #define Kmalloc (*kernel->kmalloc)
- #define Kfree (*kernel->kfree)
- #define Stricmp (*kernel->stricmp)
- #define Strlwr (*kernel->strlwr)
- #define Unixtime (*kernel->unixtim)
- #define Dostime (*kernel->dostim)
- #define Denyshare (*kernel->denyshare)
- #define Denylock (*kernel->denylock)
-
- #ifndef NULL
- # define NULL ((void *)0L)
- #endif
-
- /* Useful macros */
-
- #define IS_DIRECTORY(s) (((s)->mode & S_IFMT) == S_IFDIR)
- #define IS_SYMLINK(s) (((s)->mode & S_IFMT) == S_IFLNK)
- #define IS_SETUID(s) ((s)->mode & S_ISUID)
- #define IS_SETGID(s) ((s)->mode & S_ISGID)
- #define IS_STICKY(s) ((s)->mode & S_ISVTX)
-
- /* Conditional debugging */
-
- #ifdef NO_DEBUG
- # define DEBUG(x)
- #else
- # define DEBUG(x) (*kernel->debug)x
- #endif
-
- #ifdef NO_ALERT
- # define ALERT(x)
- #else
- # define ALERT(x) (*kernel->alert)x
- #endif
-
- #ifdef NO_TRACE
- # define TRACE(x)
- #else
- # define TRACE(x) (*kernel->trace)x
- #endif
-
- #ifdef NO_FATAL
- # define FATAL(x)
- #else
- # define FATAL(x) (*kernel->fatal)x
- #endif
-
- /* Forward declarations of the file system functions */
-
- long ram_root (int drv, fcookie *fc);
- long ram_lookup (fcookie *dir, char *name, fcookie *fc);
- long ram_creat (fcookie *dir, char *name, unsigned mode,
- int attrib, fcookie *fc);
- DEVDRV* ram_getdev (fcookie *fc, long *devsp);
- long ram_getxattr (fcookie *fc, XATTR *xattr);
- long ram_chattr (fcookie *fc, int attrib);
- long ram_chown (fcookie *fc, int uid, int gid);
- long ram_chmode (fcookie *fc, unsigned mode);
- long ram_mkdir (fcookie *fc, char *name, unsigned mode);
- long ram_rmdir (fcookie *dir, char *name);
- long ram_remove (fcookie *dir, char *name);
- long ram_getname (fcookie *root, fcookie *dir, char *pathname);
- long ram_rename (fcookie *olddir, char *oldname,
- fcookie *newdir, char *newname);
- long ram_opendir (DIR *dirh, int flags);
- long ram_readdir (DIR *dirh, char *nm, int nmlen, fcookie *fc);
- long ram_rewinddir (DIR *dirh);
- long ram_closedir (DIR *dirh);
- long ram_pathconf (fcookie *dir, int which);
- long ram_dfree (fcookie *dir, long *buf);
- long ram_writelabel (fcookie *dir, char *name);
- long ram_readlabel (fcookie *dir, char *name, int namelen);
- long ram_symlink (fcookie *dir, char *name, char *to);
- long ram_readlink (fcookie *dir, char *buf, int len);
- long ram_hardlink (fcookie *fromdir, char *fromname,
- fcookie *todir, char *toname);
- long ram_fscntl (fcookie *dir, char *name, int cmd, long arg);
- long ram_dskchng (int drv);
-
- /* Forward declarations of the device driver functions */
-
- long ram_open (FILEPTR *f);
- long ram_write (FILEPTR *f, char *buf, long bytes);
- long ram_read (FILEPTR *f, char *buf, long bytes);
- long ram_lseek (FILEPTR *f, long where, int whence);
- long ram_ioctl (FILEPTR *f, int mode, void *buf);
- long ram_datime (FILEPTR *f, int *time, int rwflag);
- long ram_close (FILEPTR *f, int pid);
- long ram_select (FILEPTR *f, long p, int mode);
- void ram_unselect (FILEPTR *f, long p, int mode);
-
- /*
- * Here is the structure used for ram files. The "next" field points to
- * the following file/dir in that directory. The "up" field points to the
- * directory the file/dir is in, or NULL for the root directory. The
- * "down" field is only used by subdirectories and points to the first
- * entry in that subdirectory. "lst" is the list of open FILEPTRs for
- * this file. "length" is the actual length, "data" the actual data, and
- * "avail" is the length of the ram block allocated for "data".
- * The field "unlink" is non-null only when the file is marked as deleted
- * and must be removed on close.
- *
- * Note that all the memory is allocated in one block: it may cause trouble
- * with big files if the memory is fragmented.
- */
-
- typedef struct ramfile {
- struct ramfile *next, *up, *down;
- char filename[RAMFILE_MAX+1];
- int uid, gid, unlink;
- short time, date;
- unsigned mode;
- FILEPTR *lst;
- long length, avail;
- char *data;
- } RAMFILE;
-
- RAMFILE ramroot;
-
- DEVDRV ram_device = {
- ram_open, ram_write, ram_read, ram_lseek, ram_ioctl, ram_datime,
- ram_close, ram_select, ram_unselect
- };
-
- FILESYS ram_filesys = {
- (FILESYS *)0,
- 0,
- ram_root,
- ram_lookup, ram_creat, ram_getdev, ram_getxattr,
- ram_chattr, ram_chown, ram_chmode,
- ram_mkdir, ram_rmdir, ram_remove, ram_getname, ram_rename,
- ram_opendir, ram_readdir, ram_rewinddir, ram_closedir,
- ram_pathconf, ram_dfree,
- ram_writelabel, ram_readlabel, ram_symlink, ram_readlink,
- ram_hardlink, ram_fscntl, ram_dskchng
- };
-
- #define DRIVE_MAP *(unsigned long *)(0x4c2L)
-
- /*
- * This function is called by the kernel when the
- * file system is being loaded, and should return the file system
- * structure
- */
-
- FILESYS *ram_init (struct kerinfo *k)
- {
- kernel = k;
-
- CCONWS("Ramdisk filesystem for MiNT (Version " VERSION ", compiled "
- __DATE__ ") by T.Bousch\r\n");
-
- /* Add drive 'R' to the list of Bios drives */
- DRIVE_MAP |= (1UL << RAMDRV);
-
- TRACE(("ram_init: initialize filesystem"));
-
- ramroot.next = ramroot.up = ramroot.down = NULL;
- ramroot.unlink = 0;
- ramroot.filename[0] = 0;
- ramroot.uid = ramroot.gid = 0;
- ramroot.time = Timestamp();
- ramroot.date = Datestamp();
- ramroot.mode = S_IFDIR | DEFAULT_DIRMODE;
- ramroot.lst = NULL;
- ramroot.length = ramroot.avail = 0L;
- ramroot.data = NULL;
-
- return &ram_filesys;
- }
-
- long ram_root (int drv, fcookie *fc)
- {
- if ((unsigned)drv == RAMDRV) {
- TRACE(("ram_root: drive %c: is a ramdisk", 'A' + RAMDRV));
- fc->fs = &ram_filesys;
- fc->dev = drv;
- fc->index = (long) &ramroot;
- return 0;
- } else {
- fc->fs = NULL; /* Not our drive */
- return EDRIVE;
- }
- }
-
- long ram_lookup (fcookie *dir, char *name, fcookie *fc)
- {
- RAMFILE *s, *d;
-
- TRACE(("ram_lookup: search name [%s]", name));
-
- d = (RAMFILE *)dir->index;
-
- if (!d || !IS_DIRECTORY(d)) {
- DEBUG(("ram_lookup: bad directory"));
- return EPTHNF;
- }
- /* Empty name and "." are the directory itself */
- if (!*name || !Stricmp(name, ".")) {
- *fc = *dir;
- return 0;
- }
- /* ".." could be a mount point */
- if (!Stricmp(name, "..")) {
- s = d->up;
- if (s) {
- fc->index = (long)s;
- fc->fs = &ram_filesys;
- fc->dev = RAMDRV;
- return 0;
- } else {
- *fc = *dir;
- return EMOUNT;
- }
- }
-
- for (s = d->down; s; s = s->next) {
- if (!Stricmp(s->filename,name))
- break;
- }
-
- if (!s) {
- DEBUG(("ram_lookup: name [%s] not found", name));
- return EFILNF;
- } else {
- fc->index = (long)s;
- fc->fs = &ram_filesys;
- fc->dev = RAMDRV;
- }
- return 0;
- }
-
- long ram_getxattr (fcookie *fc, XATTR *xattr)
- {
- RAMFILE *s;
-
- TRACE(("ram_getxattr: get file attributes"));
-
- xattr->blksize = BLKSIZE;
- xattr->dev = RAMDRV;
- xattr->nlink = 1;
- s = (RAMFILE *)fc->index;
- xattr->index = (long)s;
- xattr->uid = s->uid; xattr->gid = s->gid;
- xattr->size = s->length;
- xattr->nblocks = (s->avail + BLKSIZE - 1) / BLKSIZE;
- xattr->mtime = xattr->ctime = xattr->atime = s->time;
- xattr->mdate = xattr->cdate = xattr->adate = s->date;
- xattr->mode = s->mode;
- xattr->attr = ((s->mode & (S_IWUSR|S_IWGRP|S_IWOTH)) ? 0 : FA_RDONLY)
- | (IS_DIRECTORY(s) ? FA_DIR : 0);
- return 0;
- }
-
- long ram_chattr (fcookie *fc, int attrib)
- {
- RAMFILE *s;
-
- TRACE(("ram_chattr: new attrib 0%o", attrib));
-
- s = (RAMFILE *)fc->index;
- if (attrib & FA_RDONLY) {
- s->mode &= ~(S_IWUSR|S_IWGRP|S_IWOTH);
- } else if ( !(s->mode & (S_IWUSR|S_IWGRP|S_IWOTH)) ) {
- s->mode |= (S_IWUSR|S_IWGRP|S_IWOTH);
- }
- return 0;
- }
-
- long ram_chown (fcookie *fc, int uid, int gid)
- {
- RAMFILE *s;
-
- TRACE(("ram_chown: new owner is %d.%d", uid, gid));
-
- s = (RAMFILE *)fc->index;
- s->uid = uid;
- s->gid = gid;
- return 0;
- }
-
- long ram_chmode (fcookie *fc, unsigned mode)
- {
- RAMFILE *s;
-
- TRACE(("ram_chmode: new mode 0%o", mode));
-
- s = (RAMFILE *)fc->index;
- s->mode = (s->mode & S_IFMT) | (mode & ~S_IFMT);
- return 0;
- }
-
- /*
- * This routine removes a file or directory marked as deleted if
- * nobody needs it anymore
- */
-
- static void unlink (RAMFILE *s)
- {
- RAMFILE *d, *t, **old;
-
- if (s->lst == NULL && s->unlink != 0) {
- d = s->up;
- old = &d->down;
- for (t = d->down; t && t != s; t = t->next)
- old = &t->next;
- if (!t) {
- ALERT(("ram_unlink: file not found"));
- return;
- }
- *old = s->next;
- Kfree(s->data);
- Kfree(s);
- d->time = Timestamp();
- d->date = Datestamp();
- }
- }
-
- long ram_remove (fcookie *dir, char *name)
- {
- RAMFILE *d, *s;
-
- TRACE(("ram_remove: delete file [%s]", name));
-
- d = (RAMFILE *)dir->index;
- for (s = d->down; s; s = s->next) {
- if (!Stricmp(s->filename, name))
- break;
- }
- if (!s) {
- DEBUG(("ram_remove: file [%s] not found", name));
- return EFILNF;
- }
- if (IS_DIRECTORY(s)) {
- DEBUG(("ram_remove: [%s] is a directory", name));
- return EACCDN;
- }
- /* If d is sticky, check that we own the file */
- if (IS_STICKY(d) && Geteuid() && s->uid != Getuid()) {
- DEBUG(("ram_remove: not owner"));
- return EACCDN;
- }
- s->unlink++;
- unlink(s);
- return 0;
- }
-
- long ram_getname (fcookie *root, fcookie *dir, char *pathname)
- {
- RAMFILE *s, *d;
- char buf[PATH_MAX];
-
- *pathname = 0; /* empty string */
- d = (RAMFILE *)root->index;
- s = (RAMFILE *)dir->index;
- while (s) {
- if (s == d) {
- TRACE(("ram_getname: returned [%s]", pathname));
- return 0;
- }
- strcpy(buf, "\\");
- strcat(buf, s->filename);
- strcat(buf, pathname);
- strcpy(pathname, buf);
- s = s->up;
- }
- DEBUG(("ram_getname: path not found"));
- return EPTHNF; /* not found */
- }
-
- long ram_rename (fcookie *olddir, char *oldname,
- fcookie *newdir, char *newname)
- {
- RAMFILE *s, *d, *dold, *dnew, **old;
-
- TRACE(("ram_rename: mv %s %s", oldname, newname));
-
- /* Verify that "newname" doesn't exist */
- dnew = (RAMFILE *)newdir->index;
- for (s = dnew->down; s; s = s->next)
- if (!Stricmp(s->filename, newname)) {
- DEBUG(("ram_rename: file already exists"));
- return EACCDN;
- }
- /* Verify that "oldname" exists */
- dold = (RAMFILE *)olddir->index;
- old = &dold->down;
- for (s = dold->down; s; s = s->next)
- if (!Stricmp(s->filename, oldname))
- break;
- else old = &s->next;
- if (!s) {
- DEBUG(("ram_rename: file not found"));
- return EFILNF;
- }
- /* Verify that "newdir" is not a subdirectory of "name" */
- for (d = dnew; d; d = d->up)
- if (d == s) {
- DEBUG(("ram_rename: invalid move"));
- return EACCDN;
- }
- strncpy(s->filename, newname, RAMFILE_MAX);
- s->filename[RAMFILE_MAX] = 0;
- if (dold != dnew) {
- /* Rename across directories */
- TRACE(("ram_rename: move across directories"));
- *old = s->next;
- s->next = dnew->down;
- dnew->down = s;
- s->up = dnew;
- }
- dold->time = dnew->time = Timestamp();
- dold->date = dnew->date = Datestamp();
-
- return 0;
- }
-
- long ram_opendir (DIR *dirh, int flags)
- {
- RAMFILE *d;
-
- TRACE(("ram_opendir: open directory"));
-
- dirh->index = 0;
- d = (RAMFILE *)dirh->fc.index;
- *(RAMFILE **)(&dirh->fsstuff) = d->down; /* next file */
-
- return 0;
- }
-
- long ram_rewinddir (DIR *dirh)
- {
- RAMFILE *d;
-
- TRACE(("ram_rewinddir: rewind directory"));
-
- dirh->index = 0;
- d = (RAMFILE *)dirh->fc.index;
- *(RAMFILE **)(&dirh->fsstuff) = d->down; /* next file */
-
- return 0;
-
- }
-
- long ram_closedir (DIR *dirh)
- {
- TRACE(("ram_closedir: close directory"));
-
- return 0;
- }
-
- long ram_readdir (DIR *dirh, char *name, int namelen, fcookie *fc)
- {
- int i;
- int giveindex = (dirh->flags == 0);
- RAMFILE *s;
- char *Filename;
-
- i = dirh->index++;
- s = (RAMFILE *)dirh->fc.index; /* Current directory */
- if (i == 0) {
- /* The "." entry is the first one */
- Filename = ".";
- } else if (i == 1 && s->up != NULL) {
- /* The ".." entry is the second one */
- s = s->up;
- Filename = "..";
- } else {
- /* Any regular entry */
- s = *(RAMFILE **)(&dirh->fsstuff);
- if (!s) {
- TRACE(("ram_readdir: no more files"));
- return ENMFIL;
- }
- *(RAMFILE **)(&dirh->fsstuff) = s->next;
- Filename = s->filename;
- }
- TRACE(("ram_readdir: entry %d: %s", i, Filename));
-
- fc->index = (long)s;
- fc->fs = &ram_filesys;
- fc->dev = RAMDRV;
-
- if (giveindex) {
- namelen -= (int)sizeof(long);
- if (namelen <= 0) return ERANGE;
- *((long *)name) = (long)s;
- name += sizeof(long);
- }
- if (namelen <= strlen(Filename)) {
- DEBUG(("ram_readdir: name too long"));
- return ENAMETOOLONG;
- }
- strcpy(name, Filename);
- return 0;
- }
-
- long ram_pathconf (fcookie *dir, int which)
- {
- TRACE(("ram_pathconf: limit %d", which));
-
- switch(which) {
- case -1:
- return DP_MAXREQ;
- case DP_IOPEN:
- return UNLIMITED; /* no internal limit on open files */
- case DP_MAXLINKS:
- return 1; /* we don't have hard links */
- case DP_PATHMAX:
- return PATH_MAX; /* max. path length */
- case DP_NAMEMAX:
- return RAMFILE_MAX; /* max. length of individual name */
- case DP_ATOMIC:
- return UNLIMITED; /* all writes are atomic */
- case DP_TRUNC:
- return DP_AUTOTRUNC; /* file names are truncated */
- default:
- DEBUG(("ram_pathconf: invalid parameter"));
- return EINVFN;
- }
- }
-
- /*
- * The following (recursive) function calculates the total size of a
- * file or directory
- */
-
- static long mem_used (RAMFILE *d)
- {
- long used = 0L;
- RAMFILE *s;
-
- if (!IS_DIRECTORY(d))
- return d->avail;
- /* If it's not a regular file or a symbolic link, then */
- for (s = d->down; s; s = s->next)
- used += mem_used(s);
- return used;
- }
-
- long ram_dfree (fcookie *dir, long *buf)
- {
- long memfree, memused;
-
- TRACE(("ram_dfree: getting free disk space"));
-
- memfree = FreeMemory();
- memused = mem_used(&ramroot);
-
- *buf++ = memfree / BLKSIZE; /* free blocks */
- *buf++ = (memfree + memused) / BLKSIZE; /* total nb of blocks */
- *buf++ = BLKSIZE; /* sector size */
- *buf = 1; /* 1 sector per block */
-
- return 0;
- }
-
- long ram_writelabel (fcookie *dir, char *name)
- {
- DEBUG(("ram_writelabel: not implemented"));
- return EINVFN;
- }
-
- long ram_readlabel (fcookie *dir, char *name, int namelen)
- {
- DEBUG(("ram_readlabel: not implemented"));
- return EINVFN;
- }
-
- long ram_hardlink (fcookie *fromdir, char *fromname,
- fcookie *todir, char *toname)
- {
- DEBUG(("ram_hardlink: invalid function"));
- return EINVFN;
- }
-
- long ram_fscntl (fcookie *dir, char *name, int cmd, long arg)
- {
- DEBUG(("ram_fscntl: nothing available"));
- return EINVFN; /* Nothing for now */
- }
-
- long ram_dskchng (int drv)
- {
- TRACE(("ram_dskchng: ram disk changed ?"));
- return 0; /* No media change on a ram disk! */
- }
-
- DEVDRV *ram_getdev (fcookie *fc, long *devsp)
- {
- RAMFILE *s;
-
- TRACE(("ram_getdev: find device driver"));
-
- s = (RAMFILE *)fc->index;
- *devsp = (long)s;
- return &ram_device;
- }
-
- /*
- * Create a ram file. This function is used for regular files _and_
- * directories
- */
-
- static long
- create_ram_file (fcookie *dir, char *name, unsigned mode, fcookie *fc)
- {
- RAMFILE *s, *d;
-
- TRACE(("create_ram_file: file [%s] mode 0%o", name, mode));
-
- /* Does this name already exist ? */
- d = (RAMFILE *)dir->index;
- for (s = d->down; s; s = s->next) {
- if (!Stricmp(s->filename, name)) {
- DEBUG(("create_ram_file: file exists"));
- return EACCDN;
- }
- }
- /* The names "", "." and ".." are reserved */
- if (!*name || !Stricmp(name, ".") || !Stricmp(name, "..")) {
- DEBUG(("create_ram_file: invalid filename"));
- return EACCDN;
- }
- s = (RAMFILE *)Kmalloc(sizeof(RAMFILE));
- if (!s) {
- ALERT(("create_ram_file: out of memory"));
- return ENSMEM;
- }
- strncpy(s->filename, name, RAMFILE_MAX);
- s->filename[RAMFILE_MAX] = 0;
- /*
- * If the directory has the bits Setuid or Setgid set, then the
- * file inherits the uid or gid of its parent:
- */
- s->uid = IS_SETUID(d) ? d->uid : Getuid();
- s->gid = IS_SETGID(d) ? d->gid : Getgid();
- s->mode = mode;
- s->lst = NULL;
- s->length = s->avail = 0L;
- s->data = NULL;
- s->time = d->time = Timestamp();
- s->date = d->date = Datestamp();
- s->next = d->down;
- d->down = s;
- s->down = NULL;
- s->up = d;
- s->unlink = 0;
-
- fc->fs = &ram_filesys;
- fc->index = (long)s;
- fc->dev = dir->dev;
-
- return 0;
- }
-
- long ram_creat (fcookie *dir, char *name, unsigned mode,
- int attrib, fcookie *fc)
- {
- TRACE(("ram_creat: create regular file"));
-
- return create_ram_file (dir, name, mode|S_IFREG, fc);
- }
-
- long ram_mkdir (fcookie *fc, char *name, unsigned mode)
- {
- fcookie Dummy;
-
- TRACE(("ram_mkdir: make directory"));
-
- return create_ram_file (fc, name, mode|S_IFDIR, &Dummy);
- }
-
- long ram_rmdir (fcookie *dir, char *name)
- {
- RAMFILE *d, *s;
-
- TRACE(("ram_rmdir: remove directory [%s]", name));
-
- d = (RAMFILE *)dir->index;
- for (s = d->down; s; s = s->next) {
- if (!Stricmp(s->filename, name))
- break;
- }
- if (!s) {
- DEBUG(("ram_rmdir: directory [%s] not found", name));
- return EFILNF;
- }
- if (!IS_DIRECTORY(s) && !IS_SYMLINK(s)) {
- DEBUG(("ram_rmdir: [%s] isn't a directory", name));
- return EACCDN;
- }
- if (IS_DIRECTORY(s) && s->down) {
- DEBUG(("ram_rmdir: directory [%s] isn't empty", name));
- return EACCDN;
- }
- /* If d is sticky, check that we own the subdirectory */
- if (IS_STICKY(d) && Geteuid() && s->uid != Getuid()) {
- DEBUG(("ram_rmdir: not owner"));
- return EACCDN;
- }
- s->unlink++;
- unlink(s);
- return 0;
- }
-
- long ram_symlink (fcookie *dir, char *name, char *to)
- {
- RAMFILE *s;
- fcookie Fc;
- long ret, len;
-
- TRACE(("ram_symlink: create symbolic link"));
-
- ret = create_ram_file (dir, name, 0777|S_IFLNK, &Fc);
- if (ret == 0) {
- s = (RAMFILE *)Fc.index;
- len = strlen(to) + 1;
- s->data = Kmalloc(len);
- if (!s->data) {
- ALERT(("ram_symlink: out of memory"));
- s->unlink++;
- unlink(s);
- return ENSMEM;
- }
- s->length = s->avail = len;
- strcpy(s->data, to);
- }
- return ret;
- }
-
- long ram_readlink (fcookie *dir, char *buf, int len)
- {
- RAMFILE *s;
-
- s = (RAMFILE *)dir->index;
- if (!IS_SYMLINK(s)) {
- DEBUG(("ram_readlink: not a symbolic link"));
- return EACCDN;
- }
- if (s->length > len) {
- DEBUG(("ram_readlink: name too long"));
- return ENAMETOOLONG;
- }
- strcpy(buf, s->data);
- TRACE(("ram_readlink: returned [%s]", buf));
- return 0;
- }
-
- /*
- * The ram disk driver
- */
-
- static void enlarge_ramfile (RAMFILE *s, long new_size)
- {
- char *data2;
- long quantum;
-
- /* We choose bigger blocks for big files */
- quantum = (new_size > 16*BLKSIZE ? 4 : 1) * BLKSIZE;
- /*
- * Round to the next multiple of quantum; we assume that
- * quantum is a power of two !!
- */
- new_size = (new_size + quantum - 1) & ~(quantum - 1);
- data2 = (char *)Kmalloc(new_size);
- if (data2) {
- bcopy(s->data, data2, s->length);
- Kfree(s->data);
- s->data = data2;
- s->avail = new_size;
- } else ALERT(("enlarge_ramfile: out of memory"));
- }
-
- long ram_open (FILEPTR *f)
- {
- RAMFILE *s;
-
- TRACE(("ram_open: open file"));
-
- s = (RAMFILE *)f->devinfo;
- /* Check the sharing mode */
- if (Denyshare(s->lst, f)) {
- DEBUG(("ram_open: sharing modes conflict"));
- return EACCDN;
- }
- if (f->flags & O_TRUNC) {
- /* truncate the file */
- if (s->lst) {
- /* Can it happen ? */
- ALERT(("ram_open: O_TRUNC without O_EXCL"));
- return EACCDN;
- } else {
- Kfree(s->data);
- s->length = s->avail = 0L;
- s->data = 0;
- }
- }
- f->next = s->lst;
- s->lst = f;
-
- return 0;
- }
-
- long ram_close (FILEPTR *f, int pid)
- {
- RAMFILE *s;
- FILEPTR **old, *g;
-
- TRACE(("ram_close: close file"));
-
- if (f->links == 0) {
- s = (RAMFILE *)f->devinfo;
- old = &(s->lst);
- for (g = s->lst; g; g = g->next) {
- if (g == f)
- break;
- old = &(g->next);
- }
- if (g == NULL)
- ALERT(("ram_close: FILEPTR not found"));
- else *old = f->next;
-
- unlink(s);
- }
- return 0;
- }
-
- long ram_write (FILEPTR *f, char *buf, long nbytes)
- {
- RAMFILE *s;
- long new_size;
-
- s = (RAMFILE *)f->devinfo;
- new_size = nbytes + f->pos;
- if (new_size > s->avail)
- enlarge_ramfile(s, new_size);
- /* Hope that the file is big enough now */
- if (new_size > s->avail)
- nbytes = s->avail - f->pos;
- /* Copy the data */
- TRACE(("ram_write: %ld bytes from pos %ld", nbytes, f->pos));
- bcopy(buf, s->data + f->pos, nbytes);
- /* Update the file status */
- f->pos += nbytes;
- if (f->pos > s->length)
- s->length = f->pos;
- s->time = Timestamp();
- s->date = Datestamp();
-
- return nbytes;
- }
-
- long ram_read (FILEPTR *f, char *buf, long nbytes)
- {
- RAMFILE *s;
-
- s = (RAMFILE *)f->devinfo;
- if (nbytes + f->pos > s->length)
- nbytes = s->length - f->pos;
- /* Copy the data */
- TRACE(("ram_read: %ld bytes from pos %ld", nbytes, f->pos));
- bcopy(s->data + f->pos, buf, nbytes);
- f->pos += nbytes;
-
- return nbytes;
- }
-
- /* File locking code not yet implemented */
-
- long ram_ioctl (FILEPTR *f, int mode, void *buf)
- {
- TRACE(("ram_ioctl: mode %d", mode));
-
- if (mode == FIONREAD || mode == FIONWRITE) {
- *((long *)buf) = 1;
- return 0;
- }
- else if (mode == F_SETLK || mode == F_GETLK) {
- DEBUG(("ram_ioctl: locking not implemented"));
- return EINVFN;
- }
- DEBUG(("ram_ioctl: invalid function"));
- return EINVFN;
- }
-
- long ram_lseek(FILEPTR *f, long where, int whence)
- {
- RAMFILE *s;
- long newpos;
-
- TRACE(("ram_lseek: goto %d, mode %d", where, whence));
-
- s = (RAMFILE *)f->devinfo;
-
- switch(whence) {
- case 0:
- newpos = where;
- break;
- case 1:
- newpos = f->pos + where;
- break;
- case 2:
- newpos = s->length - where;
- break;
- default:
- DEBUG(("ram_lseek: invalid mode"));
- return EINVFN;
- }
-
- if (newpos < 0 || newpos > s->length) {
- TRACE(("ram_lseek: out of range"));
- return ERANGE;
- }
- f->pos = newpos;
- return newpos;
- }
-
- long ram_datime (FILEPTR *f, int *timeptr, int rwflag)
- {
- RAMFILE *s;
-
- s = (RAMFILE *)f->devinfo;
- if (rwflag) {
- TRACE(("ram_datime: set time and date"));
- s->time = *timeptr++;
- s->date = *timeptr;
- } else {
- TRACE(("ram_datime: get time and date"));
- *timeptr++ = s->time;
- *timeptr = s->date;
- }
- return 0;
- }
-
- long ram_select (FILEPTR *f, long p, int mode)
- {
- TRACE(("ram_select: always ready"));
-
- return 1; /* We're always ready */
- }
-
- void ram_unselect (FILEPTR *f, long p, int mode)
- {
- TRACE(("ram_unselect: nothing to do"));
-
- /* Nothing for us to do */
- }
-