[Libsysio-commit] HEAD: libsysio/src init.c ioctx.c link.c lseek.c mount.c namei.c rename.c rmdir.c
Brought to you by:
lward
|
From: Lee W. <lw...@us...> - 2004-02-14 19:49:41
|
Update of /cvsroot/libsysio/libsysio/src In directory sc8-pr-cvs1.sourceforge.net:/tmp/cvs-serv16325/src Modified Files: init.c ioctx.c link.c lseek.c mount.c namei.c rename.c rmdir.c rw.c unlink.c Log Message: + Merged in changes from namespace_assembly branch (see .../misc/init-env.sh) This provoked a bunch of bugs. See below. + Fixed a bug in _sysio_enumerate_extents(). If the IO operation was short, it would go round the loop again, mistakenly trying to fill more of the extent. + In rw.c, fixed bugs in [p]{read,write}[vx] (all the synchronous routines) that improperly propagated error returns. They were returning -errno instead of setting errno and returning -1. + In fs_native.c:doiov, fixed a bug where a zero-length IO was improperly thought to be an error. + In lseek.c:_sysio_lseek, fixed final position check to properly determine {under,over}flow. + In link.c:link, fixed the existence check. No error is returned for nonexistent files when ND_NEGOK is specified. We're supposed to check whether it's a negative entry or not. + A new macro, I_GONE, was added to inode.h. This will *try* to kill an inode but if it can't, it becomes a zombie instead. + In unlink.c:unlink, link.c:link, rename.c:rename, the driver ops were being called but the actual operation in the internal path tree was not reflected. Also, for unlink and rename, use the new I_GONE macro on the destroyed inode. + In fs_native.c:native_inop_gone, close() was always called, even when the fildes was -1. + In fs_native.c:native_inop_gone, close() was called. We really meant to call syscal(SYS_close, ...); + In namei.c:_sysio_path_walk, fixed broken symlink handling. It wasn't following symlinks anywhere if ND_NOFOLLOW was set. That flag only means that the *last* component should not be followed. + In namei.c:_sysio_path_walk, fixed buffer overrun problem for very long symlinks. + In fs_incore.c, fixed dirop_{link,rename,unlink,rmdir} because they were manipulating the system path cache and shouldn't. + In mount.c:_sysio_unmount_all we were mistakenly releasing an FS root after a failed unmount attempt. + Fixes in test_regions.c free allocated memory at the end so valgrind doesn't show a leak. Index: init.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/init.c,v retrieving revision 1.6 retrieving revision 1.7 diff -u -w -b -B -p -r1.6 -r1.7 --- init.c 6 Feb 2004 20:07:30 -0000 1.6 +++ init.c 14 Feb 2004 19:42:59 -0000 1.7 @@ -9,7 +9,7 @@ * terms of the GNU Lesser General Public License * (see cit/LGPL or http://www.gnu.org/licenses/lgpl.html) * - * Cplant(TM) Copyright 1998-2003 Sandia Corporation. + * Cplant(TM) Copyright 1998-2004 Sandia Corporation. * Under the terms of Contract DE-AC04-94AL85000, there is a non-exclusive * license for use of this work by or on behalf of the US Government. * Export of this program may require a license from the United States @@ -41,26 +41,50 @@ * le...@sa... */ +#define _BSD_SOURCE + #include <stdlib.h> +#include <unistd.h> +#include <string.h> #include <errno.h> +#include <limits.h> +#include <assert.h> #include <sys/types.h> +#include <sys/stat.h> #include <sys/queue.h> +#include <sys/uio.h> + +#include <sys/stat.h> +#include <fcntl.h> #include "sysio.h" #include "inode.h" +#include "fs.h" #include "mount.h" #include "file.h" #include "dev.h" - -#if ZERO_SUM_MEMORY -#include "fs.h" -#endif +#include "xtio.h" #ifdef STDFD_DEV #include "stdfd.h" #endif /* + * The namespace assembly buffer passes args with a `name'=`value' + * syntax. We use the following to record that in various + * routines below. + */ +struct named_argument { + const char *name; /* arg name */ + char *value; /* arg value */ +}; + +/* + * White space characters. + */ +#define IGNORE_WHITE " \t\r\n" + +/* * Sysio library initialization. Must be called before anything else in the * library. */ @@ -124,3 +148,477 @@ _sysio_shutdown() _sysio_fssw_shutdown(); #endif } + +/* + * (kind of)Duplicates strtok function. + * + * Given a buffer, returns the longest string + * that does not contain any delim characters. Will + * remove ws and any characters in the ignore string. + * Returns the token. + * + * The parameter controlling acceptance controls whether a positive + * match for some delimiter be made or not. If set, then either a delimiter + * or NUL character is success. + * + */ +static const char * +get_token(const char *buf, + int accepts, + const char *delim, + const char *ignore, + char *tbuf) +{ + char c; + int escape, quote; + + /* + * Find the first occurance of delim, recording how many + * characters lead up to it. Ignore indicated characters. + */ + escape = quote = 0; + while ((c = *buf) != '\0') { + buf++; + if (!escape) { + if (c == '\\') { + escape = 1; + continue; + } + if (c == '\"') { + quote ^= 1; + continue; + } + if (!quote) { + if (strchr(delim, c) != NULL) { + accepts = 1; + break; + } + if (strchr(ignore, c) != NULL) + continue; + } + } else + escape = 0; + *tbuf++ = c; + } + if (!accepts) + return NULL; + *tbuf = '\0'; /* NUL term */ + return buf; +} + +/* + * Parse and record named arguments given as `name = value', comma-separated + * pairs. + * + * NB: Alters the passed buffer. + */ +static char * +get_args(char *buf, struct named_argument *vec) +{ + char *nxt; + char *name, *value; + struct named_argument *v; + + for (;;) { + nxt = (char *)get_token(buf, 1, "=,", IGNORE_WHITE, name = buf); + if (!nxt || + (nxt != buf && *name == '\0' && buf + strlen(buf) == nxt)) { + buf = NULL; + break; + } + if (*name == '\0') + break; + buf = (char *)get_token(nxt, 1, ",", IGNORE_WHITE, value = nxt); + if (*value == '\0') + value = NULL; + for (v = vec; v->name; v++) + if (strcmp(v->name, name) == 0) + break; + if (!v->name) + return NULL; + v->value = value; + } + + return buf; +} + +static int +parse_mm(const char *s, dev_t *devp) +{ + unsigned long ul; + char *cp; + dev_t dev; + + ul = strtoul(s, &cp, 0); + if (*cp != '+' || ul > USHRT_MAX) + return -EINVAL; + dev = ul << 16; + s = (const char *)++cp; + ul = strtoul(s, &cp, 0); + if (*cp != '\0' || ul > USHRT_MAX) + return -EINVAL; + dev |= ul & 0xffff; + *devp = dev; + return 0; +} + +/* + * Performs the creat command for the namespace assembly + * + * NB: Alters the passed buffer. + */ +static int +do_creat(char *args) +{ + size_t len; + struct named_argument v[] = { + { "ft", NULL }, /* file type */ + { "nm", NULL }, /* name */ + { "pm", NULL }, /* permissions */ + { "ow", NULL }, /* owner */ + { "gr", NULL }, /* group */ + { "mm", NULL }, /* major + minor */ + { "str", NULL }, /* file data */ + { NULL, NULL } + }; + const char *cp; + long perms; + long owner, group; + struct pnode *dir, *pno; + mode_t mode; + struct intent intent; + dev_t dev; + int err; + + len = strlen(args); + if (get_args(args, v) - args != (ssize_t )len || + !(v[0].value && + v[1].value && + v[2].value)) + return -EINVAL; + perms = strtol(v[2].value, (char **)&cp, 0); + if (*cp || + perms < 0 || + (perms == LONG_MAX && errno == ERANGE) || + ((unsigned)perms & ~0777)) + return -EINVAL; + if (v[3].value) { + owner = strtol(v[3].value, (char **)&cp, 0); + if (*cp || + ((owner == LONG_MIN || owner == LONG_MAX) + && errno == ERANGE)) + return -EINVAL; + } else + owner = getuid(); + if (v[4].value) { + group = strtol(v[4].value, (char **)&cp, 0); + if (*cp || + ((group == LONG_MIN || group == LONG_MAX) && + errno == ERANGE)) + return -EINVAL; + } else + group = getegid(); + + if (!(dir = _sysio_cwd) && !(dir = _sysio_root)) + return -ENOENT; + err = 0; + mode = perms; + if (strcmp(v[0].value, "dir") == 0) { + INTENT_INIT(&intent, INT_CREAT, &mode, 0); + err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno); + if (err) + return err; + if (pno->p_base->pb_ino) + err = -EEXIST; + else if (IS_RDONLY(pno->p_parent, + pno->p_parent->p_base->pb_ino)) + err = -EROFS; + else { + struct inode *ino; + + ino = pno->p_parent->p_base->pb_ino; + err = (*ino->i_ops.inop_mkdir)(pno, mode); + } + P_RELE(pno); + } else if (strcmp(v[0].value, "chr") == 0) { + if (!(v[5].value && parse_mm(v[5].value, &dev) == 0)) + return -EINVAL; + mode |= S_IFCHR; + INTENT_INIT(&intent, INT_CREAT, &mode, 0); + err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno); + if (err) + return err; + if (pno->p_base->pb_ino) + err = -EEXIST; + else if (IS_RDONLY(pno->p_parent, + pno->p_parent->p_base->pb_ino)) + err = -EROFS; + else { + struct inode *ino; + + ino = pno->p_parent->p_base->pb_ino; + err = (*ino->i_ops.inop_mknod)(pno, mode, dev); + } + P_RELE(pno); + } else if (strcmp(v[0].value, "blk") == 0) { + /* + * We don't support block special files yet. + */ + return -EINVAL; + } else if (strcmp(v[0].value, "file") == 0) { + int i; + struct inode *ino; + + i = O_CREAT|O_EXCL; + INTENT_INIT(&intent, INT_CREAT, &mode, &i); + err = _sysio_namei(dir, v[1].value, ND_NEGOK, &intent, &pno); + if (err) + return err; + err = _sysio_open(pno, O_CREAT|O_EXCL, mode); + if (err) { + P_RELE(pno); + return err; + } + ino = pno->p_base->pb_ino; + if (!err && v[6].value) { + struct iovec iovec; + struct intnl_xtvec xtvec; + struct ioctx io_context; + + /* + * Deposit optional file content. + */ + iovec.iov_base = v[6].value; + iovec.iov_len = strlen(v[6].value); + xtvec.xtv_off = 0; + xtvec.xtv_len = iovec.iov_len; + IOCTX_INIT(&io_context, + 1, + (ioid_t )&io_context, + ino, + &iovec, 1, + &xtvec, 1); + _sysio_ioctx_enter(&io_context); + err = + (*ino->i_ops.inop_write)(pno->p_base->pb_ino, + &io_context); + if (!err) { + ssize_t cc; + + cc = _sysio_ioctx_wait(&io_context); + if (cc < 0) + err = cc; + else if ((size_t )cc != iovec.iov_len) + err = -EIO; /* huh? */ + } else + _sysio_ioctx_complete(&io_context); + } + i = (*ino->i_ops.inop_close)(ino); + if (!err) + err = i; + P_RELE(pno); + } else + err = -EINVAL; + + return err; +} + +/* + * Do mount. + * + * NB: The passed buffer is altered. + */ +static int +do_mnt(char *args) +{ + size_t len; + struct named_argument v[] = { + { "dev", NULL }, /* source (type:dev) */ + { "dir", NULL }, /* target dir */ + { "fl", NULL }, /* flags */ + { "da", NULL }, /* mount data */ + { NULL, NULL } + }; + char *ty, *name; + unsigned long flags; + struct pnode *dir; + + len = strlen(args); + if (get_args(args, v) - args != (ssize_t )len || + !(v[0].value && v[1].value)) + return -EINVAL; + ty = (char *)get_token(v[0].value, 1, ":", "", name = v[0].value); + flags = 0; + if (v[2].value) { + char *cp; + + /* + * Optional flags. + */ + flags = strtoul(v[2].value, &cp, 0); + if (*cp || (flags == ULONG_MAX && errno == ERANGE)) + return -EINVAL; + } + + if (strlen(v[1].value) == 1 && v[1].value[0] == PATH_SEPARATOR) { + /* + * Aha! It's root they want. Have to do that special. + */ + return _sysio_mount_root(ty, name, flags, v[3].value); + } + + if (!(dir = _sysio_cwd) && !(dir = _sysio_root)) + return -ENOENT; + return _sysio_mount(dir, ty, v[1].value, name, flags, v[3].value); +} + + +/* + * Chdir + * + * NB: Alters the passed buffer. + */ +static int +do_cd(char *args) +{ + size_t len; + struct named_argument v[] = { + { "dir", NULL }, /* directory */ + { NULL, NULL } + }; + int err; + struct pnode *dir, *pno; + + len = strlen(args); + if (get_args(args, v) - args != (ssize_t )len || !v[0].value) + return -EINVAL; + + if (!(dir = _sysio_cwd) && !(dir = _sysio_root)) + return -ENOENT; + err = _sysio_namei(dir, v[0].value, 0, NULL, &pno); + if (err) + return err; + err = _sysio_p_chdir(pno); + if (err) + P_RELE(pno); + return err; +} + +/* + * Does a chmod + * + * NB: Alters passed buffer. + */ +static int +do_chmd(char *args) +{ + size_t len; + struct named_argument v[] = { + { "src", NULL }, /* path */ + { "pm", NULL }, /* perms */ + { NULL, NULL } + }; + long perms; + char *cp; + struct intnl_stat stbuf; + int err; + struct pnode *dir, *pno; + + len = strlen(args); + if (get_args(args, v) - args != (ssize_t )len || + !(v[0].value && v[1].value)) + return -EINVAL; + perms = strtol(v[1].value, &cp, 0); + if (*cp || + perms < 0 || + (perms == LONG_MAX && errno == ERANGE) || + ((unsigned)perms & ~0777)) + return -EINVAL; + (void )memset(&stbuf, 0, sizeof(stbuf)); + stbuf.st_mode = (mode_t)perms; + + if (!(dir = _sysio_cwd) && !(dir = _sysio_root)) + return -ENOENT; + err = _sysio_namei(dir, v[0].value, 0, NULL, &pno); + if (err) + return err; + err = _sysio_setattr(pno, pno->p_base->pb_ino, SETATTR_MODE, &stbuf); + P_RELE(pno); + + return err; +} + +/* + * Execute the given cmd. + * + * NB: Buf is altered. + */ +static int +do_command(char *buf) +{ + size_t len; + char *args, *cmd; + + len = strlen(buf); + args = (char *)get_token(buf, 1, ",", IGNORE_WHITE, cmd = buf); + if (args) { + if (strcmp("creat", cmd) == 0) + return do_creat(args); + if (strcmp("mnt", cmd) == 0) + return do_mnt(args); + if (strcmp("cd", cmd) == 0) + return do_cd(args); + if (strcmp("chmd", cmd) == 0) + return do_chmd(args); + } + return -EINVAL; +} + +/* + * Given a command sequence buffer, parse it and run the given + * commands + */ +int +_sysio_boot(const char *buf) +{ + char c, *tok; + int err; + + /* + * Allocate token buffer. + */ + tok = malloc(strlen(buf)); + if (!tok) + return -ENOMEM; + err = 0; + while (1) { + /* + * Discard leading white space. + */ + while ((c = *buf) != '\0' && + !(c == '{' || strchr(IGNORE_WHITE, c) == NULL)) + buf++; + if (c == '\0') + break; + if (c != '{') { + err = -EINVAL; + break; + } + /* + * Get the command. + */ + buf = (char *)get_token(buf + 1, 0, "}", IGNORE_WHITE, tok); + if (!buf) { + err = -EINVAL; + break; + } + /* + * Perform. + */ + err = do_command(tok); + if (err) + break; + } + free(tok); + return err; +} Index: ioctx.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/ioctx.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -w -b -B -p -r1.7 -r1.8 --- ioctx.c 6 Feb 2004 20:07:30 -0000 1.7 +++ ioctx.c 14 Feb 2004 19:42:59 -0000 1.8 @@ -344,6 +344,7 @@ _sysio_enumerate_extents(const struct in const struct iovec *start; _SYSIO_OFF_T off; size_t n; + size_t remain; acc = 0; iovec.iov_len = 0; @@ -406,6 +407,7 @@ _sysio_enumerate_extents(const struct in iovec.iov_len = n; continue; } + remain = xtvec.xtv_len - n; cc = (*f)(start, iov - start, xtvec.xtv_off, @@ -416,10 +418,13 @@ _sysio_enumerate_extents(const struct in return acc; return cc; } + remain -= cc; cc += acc; if (acc && cc <= acc) abort(); /* paranoia */ acc = cc; + if (remain) + return acc; /* short */ } xtvec.xtv_off += cc; xtvec.xtv_len -= cc; Index: link.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/link.c,v retrieving revision 1.3 retrieving revision 1.4 diff -u -w -b -B -p -r1.3 -r1.4 --- link.c 26 Jan 2004 16:34:54 -0000 1.3 +++ link.c 14 Feb 2004 19:42:59 -0000 1.4 @@ -67,32 +67,34 @@ link(const char *oldpath, const char *ne goto out; if (S_ISDIR(old->p_base->pb_ino->i_mode)) { err = -EPERM; - goto error2; + goto error1; } INTENT_INIT(&intent, INT_UPDPARENT, NULL, NULL); + new = NULL; err = _sysio_namei(_sysio_cwd, newpath, ND_NEGOK, &intent, &new); - if (err && !new) - goto error2; - if (err && err != -ENOENT) { - err = -EEXIST; + if (err) goto error1; + if (new->p_base->pb_ino) { + err = -EEXIST; + goto error2; } if (old->p_mount->mnt_root != new->p_mount->mnt_root) { err = -EXDEV; - goto error1; + goto error2; } err = old->p_base->pb_ino->i_ops.inop_link(old, new); if (err) - goto error1; + goto error2; /* - * The new path-base node must point to the inode referenced by - * the old. As well, we need to record the new reference of the inode. + * The new p-node must be pointed at the inode referenced by the old. */ + assert(!new->p_base->pb_ino && old->p_base->pb_ino); new->p_base->pb_ino = old->p_base->pb_ino; I_REF(new->p_base->pb_ino); -error1: - P_RELE(new); + error2: + P_RELE(new); +error1: P_RELE(old); if (err) { errno = -err; Index: lseek.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/lseek.c,v retrieving revision 1.12 retrieving revision 1.13 diff -u -w -b -B -p -r1.12 -r1.13 --- lseek.c 6 Feb 2004 20:07:30 -0000 1.12 +++ lseek.c 14 Feb 2004 19:42:59 -0000 1.13 @@ -91,7 +91,8 @@ _sysio_lseek(int fd, _SYSIO_OFF_T offset return -EINVAL; } pos = off + offset; - if (pos < 0 || (off && pos <= off)) + if ((offset < 0 && -offset > off) || + (off && offset && pos <= off)) return -EINVAL; #ifdef O_LARGEFILE if (pos >= ((fil->f_flags & O_LARGEFILE) ? _SYSIO_OFF_T_MAX : LONG_MAX)) Index: mount.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/mount.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -w -b -B -p -r1.10 -r1.11 --- mount.c 6 Feb 2004 20:07:30 -0000 1.10 +++ mount.c 14 Feb 2004 19:42:59 -0000 1.11 @@ -273,7 +273,8 @@ _sysio_mount_root(const char *source, } int -mount(const char *source, +_sysio_mount(struct pnode *cwd, + const char *source, const char *target, const char *filesystemtype, unsigned long mountflags, @@ -296,18 +297,16 @@ mount(const char *source, * Look up the target path node. */ INTENT_INIT(&intent, INT_GETATTR, NULL, NULL); - err = _sysio_namei(_sysio_cwd, target, 0, &intent, &tgt); + err = _sysio_namei(cwd, target, 0, &intent, &tgt); if (err) - goto out; + return err; if (tgt == _sysio_root) { /* * Attempting to mount over root. */ err = -EBUSY; - P_RELE(tgt); - } - + } else { /* * Do the deed. */ @@ -317,9 +316,28 @@ mount(const char *source, data, tgt, &mnt); + } if (err) P_RELE(tgt); -out: + return err; +} + +int +mount(const char *source, + const char *target, + const char *filesystemtype, + unsigned long mountflags, + const void *data) +{ + int err; + + err = + _sysio_mount(_sysio_cwd, + source, + target, + filesystemtype, + mountflags, + data); if (err) { errno = -err; err = -1; @@ -368,11 +386,13 @@ int _sysio_unmount_all() { int err; - struct mount *mnt; + struct mount *mnt, *nxt; struct pnode *pno; err = 0; - while ((mnt = mounts.lh_first)) { + nxt = mounts.lh_first; + while ((mnt = nxt)) { + nxt = mnt->mnt_link.le_next; pno = mnt->mnt_root; /* * If this is an automount generated mount, the root @@ -394,8 +414,8 @@ _sysio_unmount_all() if (err) { #ifdef notdef if (pno->p_cover != pno) -#endif P_RELE(pno); +#endif break; } if (pno == _sysio_root) Index: namei.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/namei.c,v retrieving revision 1.10 retrieving revision 1.11 diff -u -w -b -B -p -r1.10 -r1.11 --- namei.c 6 Feb 2004 20:07:30 -0000 1.10 +++ namei.c 14 Feb 2004 19:42:59 -0000 1.11 @@ -200,9 +200,10 @@ _sysio_path_walk(struct pnode *parent, s */ for (;;) { ino = nd->nd_pno->p_base->pb_ino; - if (!(nd->nd_flags & ND_NOFOLLOW) && - S_ISLNK(ino->i_mode)) { + if (S_ISLNK(ino->i_mode) && + (next.len || !(nd->nd_flags & ND_NOFOLLOW))) { char *lpath; + ssize_t cc; struct nameidata nameidata; if (nd->nd_slicnt >= MAX_SYMLINK) { @@ -213,19 +214,21 @@ _sysio_path_walk(struct pnode *parent, s /* * Follow symbolic link. */ - lpath = malloc(MAXPATHLEN); + lpath = malloc(MAXPATHLEN + 1); if (!lpath) { err = -ENOMEM; break; } - err = + cc = ino->i_ops.inop_readlink(nd->nd_pno, lpath, MAXPATHLEN); - if (err < 0) { + if (cc < 0) { free(lpath); + err = (int )cc; break; } + lpath[cc] = '\0'; /* NUL term */ /* * Handle symbolic links with recursion. Yuck! */ Index: rename.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/rename.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -w -b -B -p -r1.2 -r1.3 --- rename.c 13 Oct 2003 21:23:44 -0000 1.2 +++ rename.c 14 Feb 2004 19:42:59 -0000 1.3 @@ -69,7 +69,7 @@ rename(const char *oldpath, const char * INTENT_INIT(&intent, INT_UPDPARENT, NULL, NULL); err = _sysio_namei(_sysio_cwd, oldpath, 0, &intent, &old); if (err) - goto out; + goto error3; /* * Resolve newpath to a path node. */ @@ -148,7 +148,8 @@ rename(const char *oldpath, const char * * a rename. However, it is onerous and I don't want to do it right * now. If it becomes an issue, we can do it later. For now, I've * elected to use the semantic that says, basically, the entire - * sub-tree must be unreferenced. + * sub-tree must be unreferenced. That's per POSIX, but it's a nasty + * this to do to the caller. */ if (_sysio_p_prune(new) != 1) { err = -EBUSY; @@ -157,11 +158,19 @@ rename(const char *oldpath, const char * err = old->p_base->pb_ino->i_ops.inop_rename(old, new); if (err) goto error1; + /* + * Reflect the successful rename in the active name space graph. + */ + if (new->p_base->pb_ino) + I_GONE(new->p_base->pb_ino); + new->p_base->pb_ino = old->p_base->pb_ino; + I_REF(new->p_base->pb_ino); error1: P_RELE(new); error2: P_RELE(old); +error3: if (err) { errno = -err; err = -1; Index: rmdir.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/rmdir.c,v retrieving revision 1.7 retrieving revision 1.8 diff -u -w -b -B -p -r1.7 -r1.8 --- rmdir.c 6 Feb 2004 20:07:30 -0000 1.7 +++ rmdir.c 14 Feb 2004 19:42:59 -0000 1.8 @@ -59,8 +59,9 @@ rmdir(const char *path) struct intent intent; int err; struct pnode *pno; - SYSIO_ENTER; + struct inode *ino; + SYSIO_ENTER; INTENT_INIT(&intent, INT_UPDPARENT, NULL, NULL); err = _sysio_namei(_sysio_cwd, path, 0, &intent, &pno); if (err) @@ -73,10 +74,11 @@ rmdir(const char *path) if (err) goto error; /* - * Invalide the path-base node. The inode reference was dropped - * by the driver. + * Invalidate the path-base node and kill the i-node. */ + ino = pno->p_base->pb_ino; pno->p_base->pb_ino = NULL; + I_GONE(ino); error: P_RELE(pno); out: Index: rw.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/rw.c,v retrieving revision 1.2 retrieving revision 1.3 diff -u -w -b -B -p -r1.2 -r1.3 --- rw.c 6 Feb 2004 20:07:30 -0000 1.2 +++ rw.c 14 Feb 2004 19:42:59 -0000 1.3 @@ -286,6 +286,7 @@ readv(int fd, const struct iovec *iov, i struct intnl_xtvec xtvector; struct ioctx *ioctx; int err; + ssize_t cc; SYSIO_ENTER; fil = _sysio_fd_find_capable(fd, O_WRONLY); @@ -301,13 +302,14 @@ readv(int fd, const struct iovec *iov, i iov, count, NULL, &xtvector, NULL, &ioctx); + if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0) + err = (int )cc; + SYSIO_LEAVE; if (err) { errno = -err; - SYSIO_LEAVE; - return -1; + cc = -1; } - SYSIO_LEAVE; - return _sysio_ioctx_wait(ioctx); + return cc; } #if defined(__GLIBC__) @@ -384,6 +386,7 @@ read(int fd, void *buf, size_t count) struct intnl_xtvec xtvector; int err; struct ioctx *ioctx; + ssize_t cc; SYSIO_ENTER; fil = _sysio_fd_find_capable(fd, O_WRONLY); @@ -401,13 +404,14 @@ read(int fd, void *buf, size_t count) &iovector, 1, NULL, &xtvector, NULL, &ioctx); + if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0) + err = (int )cc; + SYSIO_LEAVE; if (err) { errno = -err; - SYSIO_LEAVE; - return -1; + cc = -1; } - SYSIO_LEAVE; - return _sysio_ioctx_wait(ioctx); + return cc; } #ifdef __GLIBC__ @@ -512,6 +516,7 @@ _preadv(int fd, const struct iovec *iov, struct intnl_xtvec xtvector; struct ioctx *ioctx; int err; + ssize_t cc; SYSIO_ENTER; fil = _sysio_fd_find_capable(fd, O_WRONLY); @@ -528,13 +533,14 @@ _preadv(int fd, const struct iovec *iov, offset, &xtvector, NULL, &ioctx); + if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0) + err = (int )cc; + SYSIO_LEAVE; if (err) { errno = -err; - SYSIO_LEAVE; - return -1; + cc = -1; } - SYSIO_LEAVE; - return _sysio_ioctx_wait(ioctx); + return cc; } #if _LARGEFILE64_SOURCE @@ -616,6 +622,7 @@ _pread(int fd, void *buf, size_t count, struct iovec iovec; struct ioctx *ioctx; int err; + ssize_t cc; SYSIO_ENTER; fil = _sysio_fd_find_capable(fd, O_WRONLY); @@ -635,13 +642,14 @@ _pread(int fd, void *buf, size_t count, offset, &xtvec, NULL, &ioctx); + if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0) + err = (int )cc; + SYSIO_LEAVE; if (err) { errno = -err; - SYSIO_LEAVE; - return -1; + cc = -1; } - SYSIO_LEAVE; - return _sysio_ioctx_wait(ioctx); + return cc; } #if _LARGEFILE64_SOURCE @@ -847,6 +855,7 @@ writev(int fd, const struct iovec *iov, struct intnl_xtvec xtvector; struct ioctx *ioctx; int err; + ssize_t cc; SYSIO_ENTER; fil = _sysio_fd_find_capable(fd, O_RDONLY); @@ -862,13 +871,14 @@ writev(int fd, const struct iovec *iov, iov, count, NULL, &xtvector, NULL, &ioctx); + if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0) + err = (int )cc; + SYSIO_LEAVE; if (err) { errno = -err; - SYSIO_LEAVE; - return -1; + cc = -1; } - SYSIO_LEAVE; - return _sysio_ioctx_wait(ioctx); + return cc; } #ifdef __GLIBC__ @@ -937,6 +947,7 @@ write(int fd, const void *buf, size_t co struct intnl_xtvec xtvector; int err; struct ioctx *ioctx; + ssize_t cc; SYSIO_ENTER; fil = _sysio_fd_find_capable(fd, O_RDONLY); @@ -954,13 +965,14 @@ write(int fd, const void *buf, size_t co &iovector, 1, NULL, &xtvector, NULL, &ioctx); + if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0) + err = (int )cc; + SYSIO_LEAVE; if (err) { errno = -err; - SYSIO_LEAVE; - return -1; + cc = -1; } - SYSIO_LEAVE; - return _sysio_ioctx_wait(ioctx); + return cc; } #ifdef __GLIBC__ @@ -1027,6 +1039,7 @@ _pwritev(int fd, const struct iovec *iov struct intnl_xtvec xtvector; struct ioctx *ioctx; int err; + ssize_t cc; SYSIO_ENTER; fil = _sysio_fd_find_capable(fd, O_RDONLY); @@ -1043,13 +1056,14 @@ _pwritev(int fd, const struct iovec *iov offset, &xtvector, NULL, &ioctx); + if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0) + err = (int )cc; + SYSIO_LEAVE; if (err) { errno = -err; - SYSIO_LEAVE; - return -1; + cc = -1; } - SYSIO_LEAVE; - return _sysio_ioctx_wait(ioctx); + return cc; } #if _LARGEFILE64_SOURCE @@ -1131,6 +1145,7 @@ _pwrite(int fd, const void *buf, size_t struct iovec iovec; struct ioctx *ioctx; int err; + ssize_t cc; SYSIO_ENTER; fil = _sysio_fd_find_capable(fd, O_RDONLY); @@ -1150,13 +1165,14 @@ _pwrite(int fd, const void *buf, size_t offset, &xtvec, NULL, &ioctx); + if (!err && (cc = _sysio_ioctx_wait(ioctx)) < 0) + err = (int )cc; + SYSIO_LEAVE; if (err) { errno = -err; - SYSIO_LEAVE; - return -1; + cc = -1; } - SYSIO_LEAVE; - return _sysio_ioctx_wait(ioctx); + return cc; } #if _LARGEFILE64_SOURCE Index: unlink.c =================================================================== RCS file: /cvsroot/libsysio/libsysio/src/unlink.c,v retrieving revision 1.8 retrieving revision 1.9 diff -u -w -b -B -p -r1.8 -r1.9 --- unlink.c 6 Feb 2004 20:07:30 -0000 1.8 +++ unlink.c 14 Feb 2004 19:42:59 -0000 1.9 @@ -59,24 +59,36 @@ unlink(const char *path) struct intent intent; int err; struct pnode *pno; - SYSIO_ENTER; + struct inode *ino; + SYSIO_ENTER; INTENT_INIT(&intent, INT_UPDPARENT, NULL, NULL); err = _sysio_namei(_sysio_cwd, path, ND_NOFOLLOW, &intent, &pno); if (err) goto out; - if (IS_RDONLY(pno, pno->p_base->pb_ino)) { + ino = pno->p_base->pb_ino; + if (IS_RDONLY(pno, ino)) { err = -EROFS; goto error; } - err = (*pno->p_base->pb_ino->i_ops.inop_unlink)(pno); + err = (*ino->i_ops.inop_unlink)(pno); if (err) goto error; + assert(pno->p_base->pb_ino); /* - * Invalidate the path-base node. The inode reference was - * dropped by the driver. + * Invalidate the path node. */ + ino = pno->p_base->pb_ino; pno->p_base->pb_ino = NULL; + /* + * Kill the i-node. I've thought and thought about this. We + * can't allow it to be found via namei any longer because we + * can't count on generation numbers support and have no + * clue why there might be other soft-references -- Could + * be an open file. + */ + I_GONE(ino); + error: P_RELE(pno); out: |