home *** CD-ROM | disk | FTP | other *** search
- /*
- * files.c --
- * File manipulation procedures. This module is highly machine
- * dependent.
- *
- * Author:
- * See-Mong Tan
- * Modified by:
- * Rich Braun @ Kronos
- *
- * Revision history:
- *
- * $Log: files.c_v $
- * Revision 1.6 1991/05/13 17:43:50 richb
- * Correct the return value of file_freeblocks so it won't produce
- * an error if there are 0 free blocks.
- *
- * Revision 1.5 1991/04/17 18:04:30 richb
- * Correct the modification time stored when a file block is
- * written. (small bug in 3.1.)
- *
- * Revision 1.4 1991/04/11 20:36:51 richb
- * Add name truncation support.
- *
- * Revision 1.3 1991/03/15 22:39:19 richb
- * Several mods: fixed unlink and rename.
- *
- */
-
- #ifdef RCSID
- static char _rcsid_ = "$Id: files.c_v 1.6 1991/05/13 17:43:50 richb Exp $";
- #endif
-
- #include "common.h"
- #include "msc-dos.h" /* for dos drive and file routines */
- #include <direct.h> /* for dos directory ops */
- #include <fcntl.h> /* these ... */
- #include <sys/stat.h> /* for ... */
- #include <io.h> /* low level DOS access */
-
- /* Default permissions for files are 555 for read-only and 777 */
- /* for writeable. The low-order 9 bits can be modified by the */
- /* administrator. */
- u_short uperm_rdonly = UPERM_FILE | UPERM_READ | UPERM_EXEC;
- u_short uperm_write = UPERM_FILE | UPERM_READ | UPERM_WRITE | UPERM_EXEC;
- u_short uperm_dir = UPERM_DIR | UPERM_READ | UPERM_WRITE | UPERM_SEARCH;
-
- #ifdef NOVELL
- #include "novell.h" /* Novell definitions */
- static struct _uidmap {
- u_long unix_ID;
- u_long Novell_ID;
- } *uIDmappings = NULL;
- static int uIDcount;
- static u_long uIDoffset;
- static u_long gID;
- static u_short novelldirprot;
-
- static bool_t ldnovell (u_long, char *, struct nfsfattr *);
- #endif /* NOVELL */
-
- #ifdef DOSAUTH
- /* Support for handling file authentication */
- struct _authent {
- u_short uid; /* UID of file owner */
- u_short gid; /* GID of file owner */
- u_short mode; /* Protection mode bits */
- u_short reserved;
- };
- #define AUTHSIZE (sizeof (struct _authent))
- #define AUTHFILE "AUTHS.DMP"
- static int authfh = 0;
- #endif /* DOSAUTH */
-
- static int file_nsubdirs(char *);
- static bool_t file_readattr(char *, struct nfsfattr *);
- static void cvtd2uattr (u_long, struct find_t *, struct nfsfattr *);
-
- #define DRIVE_SCALINGFACTOR 2 /* scaling factor for dos drive blocks */
-
- /*
- * bool_t file_getattr(char *path, struct nfsfattr *attr) --
- * Gets attributes for designated file or directory and puts
- * the information in *attr. Returns TRUE if successful, FALSE otherwise.
- */
- bool_t file_getattr(path, attr)
- char *path;
- struct nfsfattr *attr;
- {
- if (path == NULL)
- return FALSE;
-
- /* See if info is cached in the inode tree */
-
- if (inattrget (pntoin (path), attr) != NULL)
- return TRUE;
-
- /* Else go out to disk */
- return file_readattr(path, attr);
- }
-
- /*
- * bool_t file_readattr(char *path, struct nfsfattr *attr) --
- * Reads file attributes for a file from disk.
- * Returns TRUE if successful, FALSE otherwise.
- * Adds file to directory tree if the file does not already exist in
- * the tree.
- */
- static bool_t file_readattr(path, attr)
- char *path;
- struct nfsfattr *attr;
- {
- struct find_t findbuf;
- u_long nodeid;
- char npath [10];
-
- /* Special-case the root directory */
- if (strlen (path) == 2 && path[1] == ':') {
-
- (void) bzero(attr, sizeof(struct nfsfattr));
- attr->na_blocksize = NFS_MAXDATA;
-
- /* Get attributes of volume label */
- sprintf (npath, "%s\\*.*", path);
- if (_dos_findfirst(npath, _A_VOLID, &findbuf) != 0) {
-
- /* Load attributes from findbuf */
- cvtd2uattr (nodeid, &findbuf, attr);
- }
- /* Set directory attributes */
- attr->na_type = NFDIR;
- attr->na_mode = uperm_dir;
- attr->na_nlink = 2;
- attr->na_blocks = 1; /* just say 1 block */
- attr->na_size = 1024;
-
- /* cache this info */
- inattrset (nodeid, attr);
- return TRUE;
- }
-
- /* Look for the file given */
- else if (_dos_findfirst(path, _A_NORMAL | _A_SUBDIR | _A_RDONLY,
- &findbuf) != 0) {
- /* not successful */
- if ((nodeid = pntoin(path)) != -1)
- inremnode (nodeid);
- return FALSE;
- }
- else {
- if ((nodeid = pntoin(path)) == -1)
- nodeid = addpathtodirtree(path);
-
- /* Load attributes from findbuf */
- (void) bzero(attr, sizeof(struct nfsfattr));
- cvtd2uattr (nodeid, &findbuf, attr);
-
- if (findbuf.attrib & _A_SUBDIR)
- attr->na_mode = uperm_dir;
- else if (findbuf.attrib & _A_RDONLY)
- attr->na_mode = uperm_rdonly;
- else
- attr->na_mode = uperm_write;
-
- #ifdef NOVELL
- /* Novell stuff */
- (void) ldnovell (nodeid, path+2, attr);
- #endif
- #ifdef DOSAUTH
- /* Read authentication entry */
- if (authfh != 0 && lseek (authfh, nodeid * AUTHSIZE, SEEK_SET) ==
- nodeid * AUTHSIZE) {
- struct _authent authentry;
- if (read (authfh, &authentry, AUTHSIZE) == AUTHSIZE) {
- attr->na_uid = authentry.uid;
- attr->na_gid = authentry.gid;
- attr->na_mode = authentry.mode;
- }
- }
- #endif /* DOSAUTH */
- /* cache this info */
- inattrset (nodeid, attr);
- return TRUE;
- }
- }
-
- static void cvtd2uattr (nodeid, findbuf, attr)
- u_long nodeid;
- struct find_t *findbuf;
- struct nfsfattr *attr;
- {
- int handle; /* DOS file handle */
-
- /* file protection bits and type */
- if (findbuf->attrib & _A_SUBDIR) { /* subdirectory */
- attr->na_type = NFDIR;
- attr->na_nlink = 2; /*** + file_nsubdirs(path) ***/
- /* # of subdirectories plus this one */
- }
- else if (findbuf->attrib & _A_RDONLY) { /* rdonly */
- attr->na_type = NFREG;
- attr->na_nlink = 1;
- }
- else {
- attr->na_type = NFREG; /* normal file */
- attr->na_nlink = 1;
- }
-
- /* file size in bytes */
- if (findbuf->attrib & _A_SUBDIR) { /* directory */
- attr->na_blocks = 1; /* just say 1 block */
- attr->na_size = 1024;
- }
- else {
- attr->na_size = findbuf->size;
- attr->na_blocks = findbuf->size / BASIC_BLOCKSIZE +
- (findbuf->size % BASIC_BLOCKSIZE == 0 ? 0 : 1);
- }
- /* preferred transfer size in blocks */
- attr->na_blocksize = NFS_MAXDATA;
-
- /* device # == drive # */
- attr->na_fsid = ingetfsid (nodeid);
- attr->na_rdev = attr->na_fsid;
-
- /* inode # */
- attr->na_nodeid = nodeid;
-
- /* time of last access */
- attr->na_atime.tv_usec = 0;
- attr->na_atime.tv_sec = unixtime(findbuf->wr_time, findbuf->wr_date);
-
- /* time of last write */
- attr->na_mtime = attr->na_atime; /* note all times are the same */
-
- /* time of last change */
- attr->na_ctime = attr->na_atime;
- }
-
- #ifdef NOVELL
- /*
- * u_char novell_GDH (int fsid) --
- * Get Novell directory handle for a filesystem.
- */
- u_char novell_GDH (fsid)
- int fsid;
- {
- union REGS regsin, regsout;
-
- /* Get the file system's directory handle */
- regsin.x.ax = 0xE900;
- regsin.x.dx = fsid - 1;
- intdos (®sin, ®sout);
-
- /* Return -1 error code if the permanent directory bit is not set or */
- /* the local-directory bit is set. */
- if ((regsout.h.ah & 0x83) != 1)
- return 255;
-
- return regsout.h.al;
- }
-
- /*
- * void ldnovell (u_long nodeid, char *path, struct nfsfattr *attr) --
- * Loads attributes of a Novell network file
- */
- static bool_t ldnovell (nodeid, path, attr)
- u_long nodeid;
- char *path;
- struct nfsfattr *attr;
- {
- FILE *fp, *fopen();
- int i;
- int stat;
- u_char handle;
- char fcn [10];
- union REGS regsin, regsout;
- struct SREGS segregs;
-
- if ((handle = novell_GDH (ingetfsid (nodeid))) == 255)
- return FALSE;
-
- /* Initialize the Novell ID mapping table if not set */
- if (uIDmappings == NULL) {
- uIDmappings = (struct _uidmap *) malloc (sizeof (struct _uidmap) *
- MAXNOVELLID);
- if (uIDmappings == NULL) {
- fprintf (stderr, "out of memory\n");
- abort();
- }
- uIDoffset = uIDcount = gID = 0;
-
- /* Default protection is 775 */
- novelldirprot = UPERM_OWNER | UPERM_GROUP | UPERM_READ | UPERM_SEARCH;
-
- if ((fp = fopen(IDFILE, "r")) == NULL) {
- fprintf (stderr, ">>> File %s missing\n", IDFILE);
- }
- else {
- while(fscanf(fp, "%s", fcn) != EOF) {
- /* Check command line for 'offset', 'group', 'user', */
- /* 'protection'. */
- if (fcn[0] == 'o')
- fscanf(fp, "%ld", &uIDoffset);
- else if (fcn[0] == 'g')
- fscanf(fp, "%ld", &gID);
- else if (fcn[0] == 'p')
- fscanf(fp, "%o", &novelldirprot);
- else if (fcn[0] == 'u') {
- char user[20];
- fscanf(fp, "%s %ld %ld", user,
- &uIDmappings[uIDcount].unix_ID,
- &uIDmappings[uIDcount].Novell_ID);
- if (uIDcount < MAXNOVELLID-1)
- uIDcount++;
- }
- }
- fclose (fp);
- }
- }
-
- segregs.ds = get_ds();
- segregs.es = segregs.ds;
-
- if (attr->na_type != NFDIR) {
- /* Set up the Scan File Information request block, as defined on */
- /* page 283 of the Novell API Reference, rev 1.00. */
-
- static struct _sfireq sfireq = /* These are placed in static */
- {0, 0x0F, -1, -1, 0, 0, 0}; /* memory because code here */
- static struct _sfirep sfirep; /* assumes seg register DS. */
-
- sfireq.handle = handle;
- sfireq.pathlen = strlen (path);
- sfireq.len = 6 + sfireq.pathlen;
- sfirep.len = sizeof (sfirep) -2;
- strcpy (sfireq.path, path);
-
- novell_API(0xE3, &sfireq, &sfirep, regsin, ®sout, &segregs);
- if (regsout.h.al != 0) {
- DBGPRT2 (nfsdebug, "%s sfi err %d", path, regsout.h.al);
- return FALSE;
- }
- attr->na_uid = sfirep.info.ownerID;
- attr->na_gid = gID;
- }
- else {
- /* Special case for directories: invoke Scan Directory For */
- /* Trustees system call, defined on p. 280 of Novell API Ref. */
-
- /* Load the protection bits */
- attr->na_mode = UPERM_DIR | novelldirprot;
- #if 0
- /* SDFT not supported because Novell allows a directory to be */
- /* a member of several groups while Unix only attaches one */
- /* group ID to the file. We punt and just return the same */
- /* group every time, to avoid confusion. */
-
- static struct _sdftreq sdftreq = {0, 0x0C, 0, 0, 0};
- static struct _sdftrep sdftrep;
-
- sdftreq.handle = handle;
- sdftreq.pathlen = strlen (path);
- sdftreq.len = 4 + sdftreq.pathlen;
- sdftrep.len = sizeof (sdftrep) -2;
- strcpy (sdftreq.path, path);
-
- novell_API (0xE2, &sdftreq, &sdftrep, regsin, ®sout, &segregs);
- if (regsout.h.al == 0) {
- attr->na_uid = sdftrep.ownerID;
- }
- else
- #endif /* 0 */
- {
- /* If SDFT call failed, usually due to access problems, */
- /* use the Scan Directory Info call. */
- static struct _sdireq sdireq = {0, 0x02, 0, 0, 0};
- static struct _sdirep sdirep;
-
- sdireq.handle = handle;
- sdireq.pathlen = strlen (path);
- sdireq.len = 5 + sdireq.pathlen;
- sdirep.len = sizeof (sdirep) -2;
- strcpy (sdireq.path, path);
-
- novell_API (0xE2, &sdireq, &sdirep, regsin, ®sout, &segregs);
- DBGPRT3 (nfsdebug, "SDIREQ %d: %d %ld", sdireq.handle, regsout.h.al,
- sdirep.ownerID);
- if (regsout.h.al != 0)
- return FALSE;
- attr->na_uid = sdirep.ownerID;
- attr->na_gid = gID;
- }
- }
-
- DBGPRT2 (nfslookup, "%s ID = %ld", path, attr->na_uid);
-
- /* Look for ID in mapping table */
- for (i = 0; i < uIDcount; i++)
- if (uIDmappings[i].Novell_ID == attr->na_uid) {
- attr->na_uid = uIDmappings[i].unix_ID;
- return TRUE;
- }
-
- /* Not found in mapping table: add the offset and return. */
- attr->na_uid += uIDoffset;
- return TRUE;
- }
- #endif /* NOVELL */
-
- /*
- * int file_nsubdirs(char *path) --
- * Returns # of subdirectories in the given directory.
- */
- static int file_nsubdirs(path)
- char *path;
- {
- int subdirs = 0;
- struct find_t ft;
- char name[MAXPATHNAMELEN];
- #define VALID(ft) (strcmp((ft).name, ".") != 0 && strcmp((ft).name, "..") != 0)
-
- /* Hack: this routine eats a lot of time and doesn't work anyway. */
-
- return 0;
-
- #if 0
- (void) strcpy(name, path);
- (void) strcat(name, "\\*.*"); /* append wildcard */
-
- if (_dos_findfirst(name, _A_SUBDIR, &ft) != 0)
- if (VALID(ft))
- subdirs++;
- else
- return 0;
-
- while(_dos_findnext(&ft) == 0)
- if (VALID(ft))
- subdirs++;
- DBGPRT2 (nfslookup, "dos_findfirst '%s', found %d subdirs",
- name, subdirs);
- return subdirs;
- #endif /* 0 */
-
- #undef VALID
- }
-
- /*
- * int file_freeblocks(int drive, long *free, long *total) --
- * Return # of free blocks in specified filesystem (ie. drive).
- */
- int file_freeblocks(drive, free, total)
- int drive;
- long *free, *total;
- {
- struct diskfree_t df; /* disk free */
-
- if (_dos_getdiskfree(drive, &df) != 0) { /* dos call */
- (void) fprintf(stderr, "freeblocks: err, cannot read\n");
- return -1;
- }
- /* DBGPRT2 (nfsdebug, "%c: blocks free %ld", 'A'+drive-1,
- (long) df.avail_clusters * (long) df.sectors_per_cluster); */
-
- *free = ((long)df.avail_clusters * (long)df.sectors_per_cluster)
- / DRIVE_SCALINGFACTOR;
- *total = ((long)df.total_clusters * (long)df.sectors_per_cluster)
- / DRIVE_SCALINGFACTOR;
- return 0;
- }
-
- /* a file pointer cache for read requests */
- #define FRDCSIZ 10
- static struct {
- u_long nodeid;
- FILE *fp;
- } frdc_cache[FRDCSIZ]; /* up to ten cached file handles */
-
- static int frdc_last; /* last location saved */
-
- /*
- * void frdc_save(u_long nodeid, FILE *fp) --
- * Cache read file pointers.
- */
- static void frdc_save(nodeid, fp)
- u_long nodeid;
- FILE *fp;
- {
- if (frdc_cache[frdc_last].fp != NULL)
- (void) fclose(frdc_cache[frdc_last].fp); /* throw away */
- frdc_cache[frdc_last].nodeid = nodeid;
- frdc_cache[frdc_last++].fp = fp;
- if (frdc_last == FRDCSIZ)
- frdc_last = 0;
- }
-
- /*
- * void frdc_del(u_long nodeid) --
- * Delete saved file pointer from read cache. No effect if file
- * was not cached. Closes file pointer also.
- */
- static void frdc_del(nodeid)
- u_long nodeid;
- {
- int i;
-
- for(i = 0; i < FRDCSIZ; i++) {
- if (frdc_cache[i].fp != NULL && frdc_cache[i].nodeid == nodeid) {
- (void) fclose(frdc_cache[i].fp);
- frdc_cache[i].fp = NULL;
- return;
- }
- }
- }
-
- /*
- * FILE *frdc_find(u_long nodeid) --
- * Finds cached file pointer corresponding to nodeid, or NULL
- * if no such file exists.
- */
- FILE *frdc_find(nodeid)
- u_long nodeid;
- {
- int i;
-
- for(i = 0; i < FRDCSIZ; i++) {
- if (frdc_cache[i].fp != NULL && frdc_cache[i].nodeid == nodeid)
- return frdc_cache[i].fp;
- }
-
- return NULL;
- }
-
- /*
- * int file_read(u_long nodeid, u_long offset,
- * u_long count, char *buffer) --
- * Reads count bytes at offset into buffer. Returns # of bytes read,
- * and -1 if an error occurs, or 0 for EOF or null file.
- */
- int file_read(nodeid, offset, count, buffer)
- u_long nodeid;
- u_long offset, count;
- char *buffer;
- {
- FILE *fp;
- bool_t saved = FALSE;
- int bytes = 0;
- char path [MAXPATHNAMELEN];
-
- if ((fp = frdc_find(nodeid)) != NULL) {
- saved = TRUE;
- }
- else if ((fp = fopen(intopn (nodeid, path), "rb")) == NULL)
- return -1;
-
- /* Seek to correct position */
- if (fseek(fp, (long) offset, 0) != 0) {
- if (!feof(fp)) {
- (void) fclose(fp);
- return -1;
- }
- else
- return 0;
- }
-
- /* Read from the file */
- bytes = fread(buffer, sizeof(char), (size_t) count, fp);
- if (!saved)
- frdc_save(nodeid, fp);
-
- return bytes;
- }
-
- /*
- * int file_rddir(u_long nodeid, u_long offs, struct udirect *udp) --
- * Put file information at offs in directory at path in nfs cookie
- * at *udp. Returns # of bytes in record, 0 if there are no more entries
- * or -1 for a read error.
- */
- int file_rddir(nodeid, offs, udp)
- u_long nodeid;
- u_long offs;
- struct udirect *udp;
- {
- char filename[MAXPATHNAMELEN];
- char npath[MAXPATHNAMELEN], path[MAXPATHNAMELEN];
- struct find_t findbuf;
- struct nfsfattr attr;
- u_long fnode;
-
- #define SUD 32 /* sizeof(struct udirect) */ /* full udp cookie size */
-
- if (offs == 0) {
- /* Force a read of the full directory if offset is zero. */
-
- if (intopn (nodeid, path) == NULL)
- return -1;
-
- /* look for the first file in the directory */
- (void) sprintf(npath, "%s\\*.*", path);
- if (_dos_findfirst(npath, _A_NORMAL | _A_SUBDIR |
- _A_RDONLY, &findbuf) == 0) {
-
- /* Read file attributes from each entry into inode cache */
- for (;;) {
- /* convert to lowercase and get the full path */
- (void) strtolower(findbuf.name);
- (void) sprintf(filename, "%s\\%s", path, findbuf.name);
-
- if ((fnode = pntoin(filename)) == -1)
- fnode = addpathtodirtree(filename);
- if (inattrget (fnode, &attr) == (struct nfsfattr *) NULL)
- (void) bzero (&attr, sizeof (struct nfsfattr));
- cvtd2uattr (fnode, &findbuf, &attr);
- if (findbuf.attrib & _A_SUBDIR)
- attr.na_mode = uperm_dir;
- else if (findbuf.attrib & _A_RDONLY)
- attr.na_mode = uperm_rdonly;
- else
- attr.na_mode = uperm_write;
- #ifdef NOVELL
- (void) ldnovell (fnode, filename+2, &attr);
- #endif
- /* cache this info */
- inattrset (fnode, &attr);
-
- /* fetch next entry */
- if (_dos_findnext(&findbuf) != 0)
- break;
- }
- }
- }
-
- /* fetch the proper inode */
- if ((udp->d_fileno = ingetentry (nodeid, offs / SUD, udp->d_name)) == -1)
- return -1;
-
- /* store the remaining udp info */
- udp->d_namlen = strlen(udp->d_name);
- udp->d_offset = offs + SUD;
- udp->d_reclen = UDIRSIZ(udp);
-
- /* return 0 if this is the last entry */
- if (ingetentry (nodeid, (offs / SUD) + 1, filename) == -1)
- return 0;
- else
- return udp->d_reclen;
-
- #undef SUD
- }
-
- /*
- * char *strtolower(char *s) --
- * Converts all characters in s to lower case. Returns s.
- */
- char *strtolower(s)
- char *s;
- {
- char *tmp;
-
- tmp = s;
- while(*s != '\0') {
- if (isalpha(*s) && isupper(*s))
- *s = tolower(*s);
- s++;
- }
-
- return tmp;
- }
-
- /*
- * enum nfsstat file_write(u_long nodeid, u_long offset,
- * u_long count, char *buffer) --
- * Write to file with name at offset, count bytes of data from buffer.
- * File should already exist. Returns 0 for success, or some error
- * code if not.
- */
- enum nfsstat file_write(nodeid, offset, count, buffer)
- u_long nodeid;
- u_long offset;
- u_long count;
- char *buffer;
- {
- int handle; /* write file handle */
- long newoff;
- char name [MAXPATHNAMELEN];
- int fw_num = WR_SIZ;
- struct nfsfattr attr;
- time_t now;
-
- if (intopn (nodeid, name) == NULL)
- return NFSERR_STALE;
-
- frdc_del(nodeid); /* delete from read cache */
-
- /* Get cached file attributes */
- if (inattrget (nodeid, &attr) == (struct nfsfattr *) NULL) {
- fprintf (stderr, "file_write: attrget failed\n");
- }
- else {
- /* If the file is read-only, temporarily set it to read/write */
- if (!(attr.na_mode & UCHK_WR))
- (void) _dos_setfileattr(name, _A_NORMAL);
- }
-
- /* open for writing only */
- handle = open(name, O_WRONLY | O_BINARY);
- if (handle == -1)
- return puterrno(errno); /* return error code */
-
- DBGPRT4 (nfswrite, "%s, %ld bytes at %ld (len = %ld)",
- name, count, offset, filelength (handle));
-
- newoff = lseek(handle, offset, 0);
- if (count < WR_SIZ) fw_num = count;
- if (write(handle, buffer, fw_num) == -1) {
- (void) close(handle);
- return puterrno(errno); /* some error */
- }
-
- /* Update cached file attributes */
- attr.na_size = filelength (handle);
- (void) time (&now);
- attr.na_atime.tv_usec = 0;
- attr.na_atime.tv_sec = now;
- attr.na_mtime = attr.na_atime;
- attr.na_ctime = attr.na_atime;
- (void) inattrset (nodeid, &attr);
-
- (void) close(handle);
-
- /* If the file is read-only, set its _A_RDONLY attribute */
- if (!(attr.na_mode & UCHK_WR))
- (void) _dos_setfileattr(name, _A_RDONLY);
- return NFS_OK;
- }
-
- /*
- * enum nfsstat file_create(char *name, struct nfssattr *sattr,
- * struct nfsfattr *fattr)
- * Creates a file with full path name and attributes sattr, and returns
- * the file attributes in *fattr. Adds file to directory tree.
- * Returns NFS_OK for success, or some error code for failure.
- */
- enum nfsstat file_create(name, sattr, fattr)
- char *name;
- struct nfssattr *sattr;
- struct nfsfattr *fattr;
- {
- int handle; /* file handle */
- enum nfsstat stat;
- u_long node;
- int sattribs = S_IREAD; /* set attributes */
-
- if (name == NULL)
- return NFSERR_NOENT;
-
- if ((stat = validate_path (name)) != NFS_OK)
- return (stat);
-
- if (sattr->sa_mode & UCHK_WR) /* file is writeable */
- sattribs |= S_IWRITE; /* set DOS file to be read & write */
-
- /* Remove the inode if assigned */
- if ((node = pntoin (name)) != -1) {
- frdc_del (node);
- inremnode (node);
- }
-
- #if 0
-
- /* obsolete code -- now get uid/gid from RPC header */
- if (sattr->sa_uid == -1 || sattr->sa_gid == -1) {
- char parent [MAXPATHNAMELEN];
- struct nfsfattr pattr; /* attributes of parent */
- char *strrchr();
-
- /* Set up UID and GID defaults from parent inode */
- strcpy (parent, name);
- *strrchr (parent, '\\') = '\0';
- if (!file_getattr (parent, &pattr)) {
- DBGPRT1 (nfsdebug, "no attrs %s", parent);
- }
- else {
- if (sattr->sa_uid == -1)
- sattr->sa_uid = pattr.na_uid;
- if (sattr->sa_gid == -1)
- sattr->sa_uid = pattr.na_gid;
- }
- }
- #endif
-
- DBGPRT4 (nfsdebug, "file_create %s <%o> [%ld,%ld]", name,
- (int) sattr->sa_mode, sattr->sa_uid, sattr->sa_gid);
-
- /* check if file already exists */
- if ((handle = open(name, O_CREAT | O_TRUNC, sattribs)) == -1)
- return puterrno (errno);
- close(handle);
-
- /* Add to inode tree */
- if ((node = pntoin(name)) == -1)
- node = addpathtodirtree(name);
-
- /* Set the file's ownership */
- (void) file_setowner (node, sattr->sa_uid, sattr->sa_gid);
-
- /* Read the file's attributes and return */
- if (! file_readattr(name, fattr))
- return NFSERR_IO; /* just created but not found now! */
-
- return NFS_OK;
- }
-
- /*
- * int file_setperm(char *path, long perm) --
- * Sets file permissions depending on perm. Perm is of two types,
- * uperm_write (regular file) or uperm_rdonly (read only).
- * Returns 0 for success or some error code if an error occurs.
- */
- enum nfsstat file_setperm(nodeid, perm)
- u_long nodeid;
- long perm;
- {
- int stat, attribs;
- char path [MAXPATHNAMELEN];
- struct nfsfattr attr;
-
- if (intopn(nodeid, path) == NULL) /* get file name */
- return NFSERR_STALE;
-
- #ifndef DOSAUTH
- if (perm & UPERM_WRITE) {
- attribs = _A_NORMAL;
- perm = uperm_write;
- }
- else {
- attribs = _A_RDONLY;
- perm = uperm_rdonly;
- }
- #endif
-
- stat = _dos_setfileattr(path, attribs);
- if (stat == 0) {
- /* Update cached file attributes */
- if (inattrget (nodeid, &attr) != (struct nfsfattr *) NULL) {
- attr.na_mode = perm;
- (void) inattrset (nodeid, &attr);
- return NFS_OK;
- }
- } else
- return puterrno(errno);
- }
-
- /*
- * int file_setsize(u_long nodeid, long size) --
- * Sets file size.
- * Returns 0 for success or some error code if an error occurs.
- */
- enum nfsstat file_setsize(nodeid, size)
- u_long nodeid;
- long size;
- {
- int stat, handle;
- char path [MAXPATHNAMELEN];
- struct nfsfattr attr;
-
- if (intopn(nodeid, path) == NULL) /* get file name */
- return NFSERR_STALE;
-
- if (size == 0L) {
- if ((handle = open(path, O_CREAT | O_TRUNC, S_IWRITE)) == -1)
- return puterrno (errno);
- close(handle);
-
- /* Update cached file attributes */
- if (inattrget (nodeid, &attr) != (struct nfsfattr *) NULL) {
- attr.na_size = 0;
- (void) inattrset (nodeid, &attr);
- }
- return NFS_OK;
- }
- else
- return NFSERR_IO;
- }
-
- /*
- * int file_settime(u_long nodeid, long secs) --
- * Sets file time specified by secs (# of seconds since 0000, Jan 1, 1970.
- * Returns 0 for success or some error code if an error occurs.
- */
- enum nfsstat file_settime(nodeid, secs)
- u_long nodeid;
- long secs;
- {
- int stat, handle;
- unsigned fdate, ftime;
- char path [MAXPATHNAMELEN];
- struct nfsfattr attr;
-
- if (intopn(nodeid, path) == NULL) /* get file name */
- return NFSERR_STALE;
-
- /* must open file to change time */
- if ((handle = open(path, O_RDONLY, S_IREAD)) == -1)
- return puterrno(errno);
-
- /* Convert Unix time format into DOS format */
- dostime (secs, &fdate, &ftime);
-
- stat = _dos_setftime(handle, fdate, ftime);
-
- (void) close(handle);
- if (stat != 0)
- return puterrno(errno);
- else {
- /* Update cached file attributes */
- if (inattrget (nodeid, &attr) != (struct nfsfattr *) NULL) {
- attr.na_atime.tv_usec = 0;
- attr.na_atime.tv_sec = secs;
- attr.na_mtime = attr.na_atime;
- attr.na_ctime = attr.na_atime;
- (void) inattrset (nodeid, &attr);
- }
-
- return NFS_OK;
- }
- }
-
- /*
- * int file_setowner(u_long nodeid, long uid, long gid) --
- * Sets file ownership values.
- * This can only set the values in cache, because DOS doesn't
- * support an on-disk representation.
- */
- enum nfsstat file_setowner(nodeid, uid, gid)
- u_long nodeid;
- long uid, gid;
- {
- struct nfsfattr attr;
- char path [MAXPATHNAMELEN];
-
- if (intopn (nodeid, path) == NULL)
- return NFSERR_NOENT;
- DBGPRT3 (nfsdebug, "Setting owner to [%ld,%ld] %s", uid, gid, path);
-
- if (file_getattr (path, &attr)) {
- #ifdef NOVELL
- if (!(attr.na_mode & UPERM_DIR) && uid != -1) {
- /* Set up the Scan File Information request block, as defined on */
- /* page 283 of the Novell API Reference, rev 1.00. */
-
- static struct _sfireq sfireq = /* These are placed in static */
- {0, 0x0F, -1, -1, 0, 0, 0}; /* memory because code here */
- static struct _sfirep sfirep; /* assumes seg register DS. */
- static struct _setfireq setfireq =
- {0, 0x10, 0};
- static struct _setfirep setfirep;
- u_char handle;
- union REGS regsin, regsout;
- struct SREGS segregs;
- int i;
-
- if ((handle = novell_GDH (ingetfsid (nodeid))) != 255) {
- segregs.ds = get_ds();
- segregs.es = segregs.ds;
-
- sfireq.handle = handle;
- sfireq.pathlen = strlen (path+2);
- sfireq.len = 6 + sfireq.pathlen;
- sfirep.len = sizeof (sfirep) -2;
- strcpy (sfireq.path, path+2);
-
- novell_API(0xE3, &sfireq, &sfirep, regsin, ®sout, &segregs);
- if (regsout.h.al != 0)
- return NFSERR_IO;
-
- /* Set up the Set File Info request block */
- setfireq.handle = handle;
- setfireq.pathlen = strlen (path+2);
- setfireq.len = 4 + sizeof (struct _fileinfo) + sfireq.pathlen;
- setfirep.len = sizeof (setfirep) -2;
- strcpy (setfireq.path, path+2);
- setfireq.info = sfirep.info;
- setfireq.info.size = 0;
-
- /* Look up the Novell user ID */
- setfireq.info.ownerID = uid - uIDoffset;
- for (i = 0; i < uIDcount; i++)
- if (uIDmappings[i].unix_ID == uid + uIDoffset) {
- setfireq.info.ownerID = uIDmappings[i].Novell_ID;
- break;
- }
-
- /* Issue the Set File Information request */
- novell_API(0xE3, &setfireq, &setfirep, regsin, ®sout,
- &segregs);
- if (regsout.h.al != 0)
- return NFSERR_ACCES;
- }
- }
- #endif /* NOVELL */
-
- /* Update cached file attributes */
- if (uid != -1)
- attr.na_uid = uid;
- if (gid != -1)
- attr.na_gid = gid;
- (void) inattrset (nodeid, &attr);
- return NFS_OK;
- }
- else
- return NFSERR_NOENT;
- }
-
- /*
- * int file_unlink(char *name) --
- * Removes named file.
- */
- enum nfsstat file_unlink(name)
- char *name;
- {
- u_long node;
- int stat;
-
- /* Close the file if we still have a handle to it */
- if ((node = pntoin (name)) != -1)
- frdc_del (node);
-
- /* Reset file attributes */
- (void) _dos_setfileattr(name, _A_NORMAL);
-
- /* Call unlink library function to remove the file. */
- stat = unlink(name);
- DBGPRT3 (nfserr, "unlink %s: stat = %d, len = %d", name, stat, strlen(name));
-
- /* Remove the inode associated with the file, if present. */
- if (stat == 0 && node != -1)
- inremnode (node);
- return (stat == 0) ? NFS_OK : puterrno (errno);
- }
-
-
- /*
- * int file_rename(char *oldname, char *newname) --
- * Renames a file
- */
- enum nfsstat file_rename(oldname, newname)
- char *oldname, *newname;
- {
- u_long node;
- int err;
- struct stat buf;
- enum nfsstat code;
-
- /* Close the file if we still have a handle to it */
- if ((node = pntoin (oldname)) != -1)
- frdc_del (node);
-
- /* Reset file attributes (e.g., read-only) */
- (void) _dos_setfileattr(oldname, _A_NORMAL);
-
- /* Validate the new filename */
- if ((code = validate_path (newname)) != NFS_OK)
- return (code);
-
- /* Delete destination file if present */
- if (stat (newname, &buf) == 0) {
- if (buf.st_mode & S_IFDIR)
- return NFSERR_ISDIR;
- if ((code = file_unlink (newname)) != NFS_OK)
- return code;
- }
-
- /* Call rename library function to rename the file. */
- err = rename(oldname,newname);
-
- /* Update the inode associated with the file, if present. */
- if (err == 0 && node != -1) {
- (void) inremnode (node);
- (void) addpathtodirtree(newname);
- }
- return (err == 0) ? NFS_OK : puterrno (errno);
- }
-
- /*
- * enum nfsstat validate_path (char *name) --
- * Validate a path name's syntax. Returns 0 if OK.
- * Modifies the path appropriately if NFS_TRUNCATENAMES is set.
- */
- enum nfsstat validate_path (name)
- char *name;
- {
- char *ptr, *ptr2, *strrchr(), *strchr();
- int i;
-
- if ((ptr = strrchr (name, '\\')) == (char *)NULL &&
- (ptr = strrchr (name, ':')) == (char *)NULL)
- ptr = name;
- else
- ptr++;
-
- /* Check validity of characters in final component */
- for (ptr2 = ptr; *ptr2; ) {
- if (*ptr2 <= ' ' || (*ptr2 & 0x80) || !inchvalid[*ptr2 - '!'])
- return NFSERR_INVAL;
- else
- ptr2++;
- }
-
- /* Verify there are no more than 8 chars before '.' */
- if ((i = strcspn (ptr, ".")) > 8) {
- if (!NFS_TRUNCATENAMES)
- return NFSERR_NAMETOOLONG;
- strcpy (ptr + 8, ptr + i);
- }
- if ((ptr = strchr (name, '.')) == (char *)NULL)
- return NFS_OK;
- else
- ptr++;
- if (strlen (ptr) > 3) {
- if (!NFS_TRUNCATENAMES)
- return NFSERR_NAMETOOLONG;
- ptr[3] = '\0';
- }
- return NFS_OK;
- }
-