commit - d9985b95c77fcdb2d5878cd0b9e213a66123029c
commit + 3a2c53f506aa2d07eaf0e8540f87054c622304fb
blob - ad809c212a601af1e4197a9a92ac6a64bf93205e
blob + c2b536f0788ab795824b0774ec01117bc09fb4db
--- client.c
+++ client.c
static void np_open(uint16_t, struct qid *, uint32_t);
static void np_read(uint16_t, uint32_t, void *);
static void np_write(uint16_t, uint32_t);
+static void np_stat(uint16_t, uint32_t, void *);
static void np_error(uint16_t, const char *);
static void np_errno(uint16_t);
static void topen(struct np_msg_header *, const uint8_t *, size_t);
static void tread(struct np_msg_header *, const uint8_t *, size_t);
static void twrite(struct np_msg_header *, const uint8_t *, size_t);
+static void tstat(struct np_msg_header *, const uint8_t *, size_t);
static void handle_message(struct imsg *, size_t);
ATTR_DEAD void
{
np_header(sizeof(count), Rwrite, tag);
np_write32(evb, count);
+ do_send();
+}
+
+static void
+np_stat(uint16_t tag, uint32_t count, void *data)
+{
+ np_header(count, Rstat, tag);
+ np_writebuf(evb, count, data);
do_send();
}
}
static inline void
-serialize_dirent(int dirfd, struct evbuffer *evb, struct dirent *d)
+serialize_stat(const char *fname, struct stat *sb, struct evbuffer *evb)
{
- struct stat sb;
struct qid qid;
const char *uid, *gid, *muid;
size_t tot;
uint16_t namlen, uidlen, gidlen, ulen;
- if (fstatat(dirfd, d->d_name, &sb, AT_SYMLINK_NOFOLLOW) == -1) {
- log_warn("fstatat");
- return;
- }
+ qid_update_from_sb(&qid, sb);
- qid_update_from_sb(&qid, &sb);
-
/* TODO: fill these fields */
uid = "";
gid = "";
muid = "";
- namlen = strlen(d->d_name);
+ namlen = strlen(fname);
uidlen = strlen(uid);
gidlen = strlen(gid);
ulen = strlen(muid);
tot = NPSTATSIZ(namlen, uidlen, gidlen, ulen);
if (tot > UINT32_MAX) {
log_warnx("stat info for dir entry %s would overflow",
- d->d_name);
+ fname);
return;
}
np_write16(evb, tot); /* size[2] */
- np_write16(evb, sb.st_rdev); /* type[2] */
- np_write32(evb, sb.st_dev); /* dev[4] */
+ np_write16(evb, sb->st_rdev); /* type[2] */
+ np_write32(evb, sb->st_dev); /* dev[4] */
np_qid(evb, &qid); /* qid[13] */
/* XXX: translate? */
- np_write32(evb, sb.st_mode); /* mode[4] */
+ np_write32(evb, sb->st_mode); /* mode[4] */
- np_write32(evb, sb.st_atim.tv_sec); /* atime[4] */
- np_write32(evb, sb.st_mtim.tv_sec); /* mtime[4] */
- np_write64(evb, sb.st_size); /* length[8] */
- np_string(evb, namlen, d->d_name); /* name[s] */
+ np_write32(evb, sb->st_atim.tv_sec); /* atime[4] */
+ np_write32(evb, sb->st_mtim.tv_sec); /* mtime[4] */
+ np_write64(evb, sb->st_size); /* length[8] */
+ np_string(evb, namlen, fname); /* name[s] */
np_string(evb, uidlen, uid); /* uid[s] */
np_string(evb, gidlen, gid); /* gid[s] */
np_string(evb, ulen, muid); /* muid[s] */
while (EVBUFFER_LENGTH(f->evb) < count) {
struct dirent *d;
+ struct stat sb;
if ((d = readdir(f->dir)) == NULL)
break;
- serialize_dirent(f->fd, f->evb, d);
+ if (fstatat(f->fd, d->d_name, &sb, 0) == -1) {
+ warn("fstatat");
+ continue;
+ }
+ serialize_stat(d->d_name, &sb, f->evb);
}
count = MIN(count, EVBUFFER_LENGTH(f->evb));
np_errno(hdr->tag);
else
np_write(hdr->tag, r);
+}
+
+static void
+tstat(struct np_msg_header *hdr, const uint8_t *data, size_t len)
+{
+ struct evbuffer *evb;
+ struct stat sb;
+ struct fid *f;
+ const char *fname;
+ int r;
+ uint32_t fid;
+
+ /* fid[4] */
+ if (!NPREAD32("fid", &fid, &data, &len)) {
+ client_send_listener(IMSG_CLOSE, NULL, 0);
+ client_shutdown();
+ return;
+ }
+
+ /*
+ * plan9' stat(9P) is not clear on whether the stat is allowed
+ * on opened fids or not.
+ */
+ if ((f = fid_by_id(fid)) == NULL) {
+ np_error(hdr->tag, "invalid fid");
+ return;
+ }
+
+ if ((evb = evbuffer_new()) == NULL)
+ fatal("evbuffer_new");
+
+ if (f->qid->type & QTDIR) {
+ fname = ".";
+ r = fstat(f->qid->fd, &sb);
+ } else {
+ fname = f->qid->fpath;
+ r = fstatat(f->qid->fd, f->qid->fpath, &sb, 0);
+ }
+
+ if (r == -1) {
+ np_errno(hdr->tag);
+ evbuffer_free(evb);
+ return;
+ }
+
+ serialize_stat(fname, &sb, evb);
+ np_stat(hdr->tag, EVBUFFER_LENGTH(evb), EVBUFFER_DATA(evb));
+ evbuffer_free(evb);
}
static void
{Topen, topen},
{Tread, tread},
{Twrite, twrite},
+ {Tstat, tstat},
};
struct np_msg_header hdr;
size_t i;