#endif
#include <sys/queue.h>
-#include "xtio.h"
#include "sysio.h"
+#include "xtio.h"
#include "fs.h"
#include "mount.h"
#include "inode.h"
*/
struct incore_inode {
LIST_ENTRY(incore_inode) ici_link; /* i-nodes list link */
- unsigned ici_revalidate : 1; /* synch sys inode? */
struct intnl_stat ici_st; /* attrs */
struct file_identifier ici_fileid; /* file ID */
void *ici_data; /* file data */
struct inode *ino,
unsigned mask,
struct intnl_stat *stbuf);
-static ssize_t _sysio_incore_dirop_getdirentries(struct inode *ino,
- char *buf,
- size_t nbytes,
- _SYSIO_OFF_T *basep);
+static ssize_t _sysio_incore_dirop_filldirentries(struct inode *ino,
+ _SYSIO_OFF_T *posp,
+ char *buf,
+ size_t nbytes);
static int _sysio_incore_dirop_mkdir(struct pnode *pno, mode_t mode);
static int _sysio_incore_dirop_rmdir(struct pnode *pno);
static int _sysio_incore_inop_open(struct pnode *pno, int flags, mode_t mode);
#define _sysio_incore_dirop_symlink \
(int (*)(struct pnode *, const char *))_sysio_do_enosys
#define _sysio_incore_dirop_readlink \
- (int (*)(struct pnode *, char *, size_t))_sysio_do_einval
+ (int (*)(struct pnode *, char *, size_t))_sysio_do_enosys
#define _sysio_incore_dirop_read \
(int (*)(struct inode *, \
struct ioctx *))_sysio_do_eisdir
_sysio_incore_dirop_lookup,
_sysio_incore_inop_getattr,
_sysio_incore_inop_setattr,
- _sysio_incore_dirop_getdirentries,
+ _sysio_incore_dirop_filldirentries,
_sysio_incore_dirop_mkdir,
_sysio_incore_dirop_rmdir,
_sysio_incore_dirop_symlink,
struct inode **, \
struct intent *, \
const char *))_sysio_do_illop
-#define _sysio_incore_filop_getdirentries \
+#define _sysio_incore_filop_filldirentries \
(ssize_t (*)(struct inode *, \
- char *, \
- size_t, \
- _SYSIO_OFF_T *))_sysio_do_illop
+ _SYSIO_OFF_T *, \
+ char *, \
+ size_t))_sysio_do_illop
#define _sysio_incore_filop_mkdir \
(int (*)(struct pnode *, mode_t))_sysio_do_illop
#define _sysio_incore_filop_rmdir \
_sysio_incore_filop_lookup,
_sysio_incore_inop_getattr,
_sysio_incore_inop_setattr,
- _sysio_incore_filop_getdirentries,
+ _sysio_incore_filop_filldirentries,
_sysio_incore_filop_mkdir,
_sysio_incore_filop_rmdir,
_sysio_incore_filop_symlink,
_sysio_incore_filop_lookup,
_sysio_incore_inop_getattr,
_sysio_incore_inop_setattr,
- _sysio_incore_filop_getdirentries,
+ _sysio_incore_filop_filldirentries,
_sysio_incore_filop_mkdir,
_sysio_incore_filop_rmdir,
_sysio_incore_filop_symlink,
icino = malloc(sizeof(struct incore_inode));
if (!icino)
return NULL;
- icino->ici_revalidate = 0;
icino->ici_st = *st;
icino->ici_fileid.fid_data = &icino->ici_st.st_ino;
icino->ici_fileid.fid_len = sizeof(icino->ici_st.st_ino);
* Source is a specification for the root attributes of this
* new file system in the format:
*
- * <permissions>+<owner>+<group>
+ * <permissions>[+<owner>][-<group>]
*/
ul = strtoul(source, &cp, 0);
mode = (mode_t )ul & 07777;
- if (*cp != '+' ||
- (ul == ULONG_MAX && errno == ERANGE) ||
- (unsigned long)mode != ul ||
- mode > 07777)
- return -EINVAL;
- source = cp;
- l = strtol(source, &cp, 0);
- uid = (uid_t )l;
- if (*cp != '+' ||
- ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) ||
- (long )uid != l)
- return -EINVAL;
- source = cp;
- l = strtol(source, &cp, 0);
- gid = (gid_t )l;
- if (*cp ||
- ((l == LONG_MIN || l == LONG_MAX) && errno == ERANGE) ||
- (long )gid != l)
- return -EINVAL;
+ uid = getuid(); /* default */
+ gid = getgid(); /* default */
+ if (*cp != '\0') {
+ /*
+ * Get user and/or group.
+ */
+ if (*cp != '+' ||
+ (ul == ULONG_MAX && errno == ERANGE) ||
+ (unsigned long)mode != ul ||
+ mode > 07777)
+ return -EINVAL;
+ source = cp;
+ l = strtol(source, &cp, 0);
+ uid = (uid_t )l;
+ if (((l == LONG_MIN || l == LONG_MAX) &&
+ errno == ERANGE) ||
+ (long )uid != l)
+ return -EINVAL;
+ if (*cp != '+')
+ return -EINVAL;
+ source = cp;
+ l = strtol(source, &cp, 0);
+ gid = (gid_t )l;
+ if (((l == LONG_MIN || l == LONG_MAX) &&
+ errno == ERANGE) ||
+ (long )gid != l)
+ return -EINVAL;
+ if (*cp != '\0')
+ return -EINVAL;
+ }
err = 0;
rooti =
_sysio_i_new(fs,
&icino->ici_fileid,
- icino->ici_st.st_mode,
- 0,
+ &icino->ici_st,
1,
&_sysio_incore_dir_ops,
icino);
static struct intnl_dirent *
incore_directory_match(struct intnl_dirent *de,
- size_t reclen __IS_UNUSED,
+ size_t reclen,
struct lookup_data *ld)
{
+ size_t len;
#if defined(BSD) || defined(REDSTORM)
if (IFTODT(de->d_type) == DT_WHT)
return NULL;
#endif
- if (
#ifdef _DIRENT_HAVE_D_NAMLEN
- ld->name->len == de->d_namlen &&
+ len = de->d_namlen;
+#else
+ {
+ const char *cp, *end;
+
+ cp = de->d_name;
+ end = (const char *)de + reclen;
+ while (cp < end && *cp != '\0')
+ cp++;
+ len = cp - de->d_name;
+ }
#endif
+ if (ld->name->len == len &&
strncmp(de->d_name, ld->name->name, ld->name->len) == 0)
return de;
ld->de = de;
if (*inop) {
icino = I2IC(*inop);
assert(icino);
- if (icino->ici_revalidate) {
- (*inop)->i_mode = icino->ici_st.st_mode;
- icino->ici_revalidate = 0;
- }
+ (*inop)->i_stbuf = icino->ici_st;
return 0;
}
ino =
_sysio_i_new(ino->i_fs,
&icino->ici_fileid,
- icino->ici_st.st_mode,
- 0,
+ &icino->ici_st
1,
ops,
icino);
if (mask & SETATTR_MODE) {
icino->ici_st.st_mode =
(icino->ici_st.st_mode & S_IFMT) | (stbuf->st_mode & 07777);
- icino->ici_revalidate = 1;
}
if (mask & SETATTR_MTIME)
icino->ici_st.st_mtime = stbuf->st_mtime;
icino->ici_st.st_gid = stbuf->st_gid;
icino->ici_st.st_ctime = time(NULL);
+ ino->i_stbuf = icino->ici_st;
out:
return err;
}
struct copy_info {
void *data;
size_t nbytes;
+ unsigned count;
};
/*
* Eumeration callback.
*
* Note:
- * On those systems supporting white-out entries, they are returned. On
- * systems without, they are not.
+ * Whiteout entries are never returned.
*/
static void *
incore_directory_enumerate(struct intnl_dirent *de,
size_t reclen,
struct copy_info *cinfo) {
+#ifdef DT_WHT
+ if (de->d_type == DT_WHT) {
+ /*
+ * Keep going but skip the copy.
+ */
+ return NULL;
+ }
+#endif
+ cinfo->count++;
if (reclen > cinfo->nbytes)
return de;
(void *)memcpy(cinfo->data, de, reclen);
}
static ssize_t
-_sysio_incore_dirop_getdirentries(struct inode *ino,
- char *buf,
- size_t nbytes,
- _SYSIO_OFF_T *basep)
+_sysio_incore_dirop_filldirentries(struct inode *ino,
+ _SYSIO_OFF_T *posp,
+ char *buf,
+ size_t nbytes)
{
struct incore_inode *icino = I2IC(ino);
off_t off;
struct intnl_dirent *de;
struct copy_info copy_info;
- if (*basep > icino->ici_st.st_size)
+ if (*posp >= icino->ici_st.st_size)
return 0;
de =
incore_directory_probe(icino->ici_data,
icino->ici_st.st_size,
- *basep,
+ *posp,
(probe_ty )incore_directory_position,
NULL,
- (char *)icino->ici_data + *basep);
+ (char *)icino->ici_data + *posp);
if (!de) {
/*
* Past EOF.
*/
- *basep = 0;
return 0;
}
copy_info.data = buf;
copy_info.nbytes = nbytes;
+ copy_info.count = 0;
off = (char *)de - (char *)icino->ici_data;
de =
incore_directory_probe(de,
(probe_ty )incore_directory_enumerate,
NULL,
©_info);
- nbytes -= copy_info.nbytes;
icino->ici_st.st_atime = time(NULL);
+ if (nbytes == copy_info.nbytes && copy_info.count)
+ return -EINVAL;
+ nbytes -= copy_info.nbytes;
+#if 0
if (!nbytes)
return -EOVERFLOW;
- *basep = nbytes;
+#endif
+ *posp += nbytes;
return (ssize_t )nbytes;
}
ino =
_sysio_i_new(pno->p_parent->p_base->pb_ino->i_fs,
&icino->ici_fileid,
- stat.st_mode,
- 0,
+ &stat,
1,
&_sysio_incore_dir_ops,
icino);
}
static int
-incore_create(struct pnode *pno, struct intnl_stat *st)
+incore_create(struct pnode *pno, struct intnl_stat *stat)
{
struct inode *dino, *ino;
struct incore_inode *icino;
dino = pno->p_parent->p_base->pb_ino;
assert(dino);
- icino = incore_i_alloc(FS2ICFS(dino->i_fs), st);
+ icino = incore_i_alloc(FS2ICFS(dino->i_fs), stat);
if (!icino)
return -ENOSPC;
ino =
_sysio_i_new(dino->i_fs,
&icino->ici_fileid,
- st->st_mode,
- st->st_rdev,
+ stat,
1,
- S_ISREG(st->st_mode)
+ S_ISREG(stat->st_mode)
? &_sysio_incore_file_ops
: &_sysio_incore_dev_ops,
icino);
err =
incore_directory_insert(I2IC(dino),
&pno->p_base->pb_name,
- st->st_ino,
+ stat->st_ino,
INCORE_D_TYPEOF(icino->ici_st.st_mode));
if (err) {
I_RELE(ino);
int err;
assert(!new->p_base->pb_ino);
- assert(!S_ISDIR(old->p_base->pb_ino->i_mode));
+ assert(!S_ISDIR(old->p_base->pb_ino->i_stbuf.st_mode));
/*
* Can bump the link count?