commit - e41d2c2b9a245fd97e4a6e1d1936de112964dfe3
commit + c7f4e1bdfe5b7c7a55f9c97c6098cd057643288b
blob - 69d8e205be0a8b4910b3547b9e86177025ebe76d
blob + ed67c148460e58993c335528368deb8e2b17052a
--- client.c
+++ client.c
#include <sys/stat.h>
-#include <assert.h>
#include <dirent.h>
#include <endian.h>
#include <errno.h>
(sizeof(type) == 8 && (val) > INT64_MAX) || \
(sizeof(type) != 4 && sizeof(type) != 8))
-STAILQ_HEAD(qidhead, qid) qids;
struct qid {
- /* definition of a qid */
uint64_t path;
uint32_t vers;
uint8_t type;
+};
+STAILQ_HEAD(dirhead, dir) dirs;
+struct dir {
int refcount;
-
int fd;
-
- STAILQ_ENTRY(qid) entries;
+ STAILQ_ENTRY(dir) entries;
};
STAILQ_HEAD(fidhead, fid) fids;
* file descriptor and iomode the flags passed to open(2).
*/
int fd;
- DIR *dir;
+ DIR *d;
struct evbuffer *evb;
/*
*/
uint64_t offset;
- struct qid *qid;
+ struct qid qid;
+ struct dir *dir;
STAILQ_ENTRY(fid) entries;
};
static int client_send_listener(int, const void *, uint16_t);
static void qid_update_from_sb(struct qid *, struct stat *);
-static struct qid *qid_from_fd(int, struct stat *);
-static struct qid *qid_incref(struct qid *);
-static void qid_decref(struct qid *);
-static struct fid *new_fid(struct qid *, uint32_t, const char *);
+static struct dir *new_dir(int);
+static struct dir *dir_incref(struct dir *);
+static void dir_decref(struct dir *);
+
+static struct fid *new_fid(struct dir *, uint32_t, const char *, struct qid *);
static struct fid *fid_by_id(uint32_t);
static void free_fid(struct fid *);
}
/* creates a qid given a fd */
-static struct qid *
-qid_from_fd(int fd, struct stat *s)
+static struct dir *
+new_dir(int fd)
{
- struct qid *qid;
- struct stat sb;
+ struct dir *dir;
- if ((qid = calloc(1, sizeof(*qid))) == NULL)
+ if ((dir = calloc(1, sizeof(*dir))) == NULL)
return NULL;
- qid->fd = fd;
-
- if (s == NULL) {
- s = &sb;
- if (fstat(fd, &sb) == -1)
- fatal("fstat");
- }
-
- qid_update_from_sb(qid, s);
-
- STAILQ_INSERT_HEAD(&qids, qid, entries);
-
- return qid;
+ dir->fd = fd;
+ STAILQ_INSERT_HEAD(&dirs, dir, entries);
+ return dir;
}
-static struct qid *
-qid_incref(struct qid *qid)
+static struct dir *
+dir_incref(struct dir *dir)
{
- qid->refcount++;
- return qid;
+ dir->refcount++;
+ return dir;
}
static void
-qid_decref(struct qid *qid)
+dir_decref(struct dir *dir)
{
- if (--qid->refcount > 0)
+ if (--dir->refcount > 0)
return;
- STAILQ_REMOVE(&qids, qid, qid, entries);
+ STAILQ_REMOVE(&dirs, dir, dir, entries);
- close(qid->fd);
- free(qid);
+ close(dir->fd);
+ free(dir);
}
static struct fid *
-new_fid(struct qid *qid, uint32_t fid, const char *path)
+new_fid(struct dir *dir, uint32_t fid, const char *path, struct qid *qid)
{
- struct fid *f;
+ struct fid *f;
+ struct qid q;
+ struct stat sb;
+
+ if (qid == NULL) {
+ if (fstatat(dir->fd, path, &sb, 0)) {
+ log_warn("fstatat(%s)", path);
+ return NULL;
+ }
+ qid_update_from_sb(&q, &sb);
+ qid = &q;
+ }
if ((f = calloc(1, sizeof(*f))) == NULL)
return NULL;
- f->qid = qid_incref(qid);
+ f->dir = dir_incref(dir);
f->fid = fid;
f->fd = -1;
- if (path != NULL)
- strlcpy(f->fpath, path, sizeof(f->fpath));
+ strlcpy(f->fpath, path, sizeof(f->fpath));
+
+ memcpy(&f->qid, qid, sizeof(f->qid));
STAILQ_INSERT_HEAD(&fids, f, entries);
int r;
if (f->fd != -1) {
- if (f->dir != NULL)
- r = closedir(f->dir);
+ if (f->d != NULL)
+ r = closedir(f->d);
else
r = close(f->fd);
/* try to honour ORCLOSE if requested */
if (f->iomode & O_CLOEXEC)
- unlinkat(f->qid->fd, f->fpath, 0);
+ unlinkat(f->dir->fd, f->fpath, 0);
}
- qid_decref(f->qid);
+ dir_decref(f->dir);
STAILQ_REMOVE(&fids, f, fid, entries);
free(f);
static void
tattach(struct np_msg_header *hdr, const uint8_t *data, size_t len)
{
- struct qid *qid;
+ struct dir *dir;
struct fid *f;
uint32_t fid, afid;
int fd;
if ((fd = open(aname, O_RDONLY|O_DIRECTORY)) == -1)
goto fail;
- if ((qid = qid_from_fd(fd, NULL)) == NULL)
+ if ((dir = new_dir(fd)) == NULL)
goto fail;
log_debug("attached %s to %d", aname, fid);
- if ((f = new_fid(qid, fid, aname)) == NULL) {
- qid_decref(qid);
+ if ((f = new_fid(dir, fid, aname, NULL)) == NULL) {
+ dir_decref(dir);
goto fail;
}
- np_attach(hdr->tag, qid);
+ np_attach(hdr->tag, &f->qid);
return;
fail:
twalk(struct np_msg_header *hdr, const uint8_t *data, size_t len)
{
struct stat sb;
- struct qid *qid, wqid[MAXWELEM] = {0};
+ struct dir *dir;
+ struct qid wqid[MAXWELEM] = {0};
struct fid *f, *nf;
uint32_t fid, newfid;
uint16_t nwname;
* newfid?
*/
if (nf == NULL &&
- (nf = new_fid(f->qid, newfid, f->fpath)) == NULL)
+ (nf = new_fid(f->dir, newfid, f->fpath, &f->qid)) == NULL)
fatal("new_fid duplication");
np_walk(hdr->tag, 0, NULL);
return;
}
- if (f->qid->type != QTDIR) {
+ if (!(f->qid.type & QTDIR)) {
np_error(hdr->tag, "fid doesn't represent a directory");
return;
}
- oldfd = f->qid->fd;
+ oldfd = f->dir->fd;
for (nwqid = 0; nwqid < nwname; nwqid++) {
switch (NPREADSTR("wname", wnam, sizeof(wnam), &data, &len)) {
if (fd == -1 && nwqid+1 == nwname)
continue;
- if (oldfd != f->qid->fd)
+ if (oldfd != f->dir->fd)
close(oldfd);
oldfd = fd;
}
/*
* If fd is -1 we've reached a file, otherwise we've just
* reached another directory. We must pay attention to what
- * file descriptor we use to create the qid, because if we've
- * reached a file and oldfd is f->qid->fd then we *must* share
- * the same qid (it was a walk of one path from a directory to a
+ * file descriptor we use to create the dir, because if we've
+ * reached a file and oldfd is f->dir->fd then we *must* share
+ * the same dir (it was a walk of one path from a directory to a
* file, otherwise fun is bound to happen as soon as the client
* closes the fid for the directory but keeps the one for the
* file.
*/
- if (fd == -1 && oldfd == f->qid->fd)
- qid = f->qid;
+ if (fd == -1 && oldfd == f->dir->fd)
+ dir = f->dir;
else if (fd == -1)
- qid = qid_from_fd(oldfd, NULL);
+ dir = new_dir(oldfd);
else
- qid = qid_from_fd(fd, &sb);
+ dir = new_dir(fd);
- if (qid == NULL)
- fatal("qid_from_fd");
+ if (dir == NULL)
+ fatal("new_dir");
if (nf == NULL) {
- const char *fnam = NULL;
-
- /* reached the file wnam */
- if (fd == -1)
- fnam = wnam;
-
- if ((nf = new_fid(qid, newfid, fnam)) == NULL)
+ if ((nf = new_fid(dir, newfid, wnam, &wqid[nwqid-1])) == NULL)
fatal("new fid");
} else {
- /* update the qid */
- qid_decref(nf->qid);
- nf->qid = qid_incref(qid);
+ /* update the dir */
+ dir_decref(nf->dir);
+ nf->dir = dir_incref(dir);
}
np_walk(hdr->tag, nwqid, wqid);
return;
cantopen:
- if (oldfd != f->qid->fd)
+ if (oldfd != f->dir->fd)
close(oldfd);
no = errno;
if (nwqid == 0)
}
path = f->fpath;
- if (*path == '\0')
+ if (f->qid.type & QTDIR)
path = ".";
- if ((f->fd = openat(f->qid->fd, path, f->iomode)) == -1) {
+ if ((f->fd = openat(f->dir->fd, path, f->iomode)) == -1) {
np_error(hdr->tag, strerror(errno));
return;
}
fatal("fstat");
if (S_ISDIR(sb.st_mode)) {
- assert(f->qid->type & QTDIR);
- if ((f->dir = fdopendir(f->fd)) == NULL) {
+ if ((f->d = fdopendir(f->fd)) == NULL) {
np_errno(hdr->tag);
close(f->fd);
f->fd = -1;
if ((f->evb = evbuffer_new()) == NULL) {
np_errno(hdr->tag);
- closedir(f->dir);
- f->dir = NULL;
+ closedir(f->d);
+ f->d = NULL;
f->fd = -1;
}
}
return;
}
- if (!(f->qid->type & QTDIR)) {
+ if (!(f->qid.type & QTDIR)) {
np_error(hdr->tag, "fid doesn't identify a directory");
return;
}
if (perm & 0x80000000) {
/* create a directory */
- f->fd = mkdirat(f->qid->fd, name, 0755);
+ f->fd = mkdirat(f->dir->fd, name, 0755);
} else {
/* create a file */
- f->fd = openat(f->qid->fd, name, f->iomode | O_CREAT | O_TRUNC,
+ f->fd = openat(f->dir->fd, name, f->iomode | O_CREAT | O_TRUNC,
0644);
}
fatal("fstat");
if (S_ISDIR(sb.st_mode)) {
- if ((f->dir = fdopendir(f->fd)) == NULL) {
+ if ((f->d = fdopendir(f->fd)) == NULL) {
np_errno(hdr->tag);
close(f->fd);
f->fd = -1;
if ((f->evb = evbuffer_new()) == NULL) {
np_errno(hdr->tag);
- closedir(f->dir);
- f->dir = NULL;
+ closedir(f->d);
+ f->d = NULL;
f->fd = -1;
}
}
return;
}
- if (f->dir == NULL) {
+ if (f->d == NULL) {
/* read a file */
r = pread(f->fd, buf, sizeof(buf), (off_t)off);
if (r == -1)
np_read(hdr->tag, r, buf);
} else {
if (off == 0 && f->offset != 0) {
- rewinddir(f->dir);
+ rewinddir(f->d);
f->offset = 0;
}
struct dirent *d;
struct stat sb;
- if ((d = readdir(f->dir)) == NULL)
+ if ((d = readdir(f->d)) == NULL)
break;
if (fstatat(f->fd, d->d_name, &sb, 0) == -1) {
warn("fstatat");
if (f->fd != -1)
r = fstat(f->fd, &sb);
else
- r = fstatat(f->qid->fd, f->fpath, &sb, 0);
+ r = fstatat(f->dir->fd, f->fpath, &sb, 0);
if (r == -1) {
np_errno(hdr->tag);
return;
}
- if (f->fd == -1 || f->dir == NULL) /* unlink file */
- r = unlinkat(f->qid->fd, f->fpath, 0);
+ if (f->fd == -1 || f->d == NULL) /* unlink file */
+ r = unlinkat(f->dir->fd, f->fpath, 0);
else /* directory */
- r = unlinkat(f->qid->fd, f->fpath, AT_REMOVEDIR);
+ r = unlinkat(f->dir->fd, f->fpath, AT_REMOVEDIR);
if (r == -1)
np_errno(hdr->tag);