2016-01-23 18:45:17 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2016 Jakub Klama <jceel@FreeBSD.org>
|
|
|
|
* All rights reserved
|
|
|
|
*
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
|
|
* modification, are permitted providing that the following conditions
|
|
|
|
* are met:
|
|
|
|
* 1. Redistributions of source code must retain the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer.
|
|
|
|
* 2. Redistributions in binary form must reproduce the above copyright
|
|
|
|
* notice, this list of conditions and the following disclaimer in the
|
|
|
|
* documentation and/or other materials provided with the distribution.
|
|
|
|
*
|
|
|
|
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
|
|
|
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
|
|
|
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
|
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
|
|
|
|
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
|
|
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
|
|
|
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
|
|
|
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
|
|
|
|
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
|
|
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
|
|
|
* POSSIBILITY OF SUCH DAMAGE.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
/*
|
|
|
|
* Based on libixp code: ©2007-2010 Kris Maglione <maglione.k at Gmail>
|
|
|
|
*/
|
2016-01-23 18:45:17 +01:00
|
|
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2016-01-28 00:40:43 +01:00
|
|
|
#include <assert.h>
|
2016-01-23 18:45:17 +01:00
|
|
|
#include <sys/types.h>
|
2016-01-28 00:40:43 +01:00
|
|
|
#include <sys/param.h>
|
|
|
|
#include <sys/uio.h>
|
2016-01-23 18:45:17 +01:00
|
|
|
#include "lib9p.h"
|
2016-01-31 01:56:11 +01:00
|
|
|
#include "lib9p_impl.h"
|
2016-01-23 18:45:17 +01:00
|
|
|
|
|
|
|
#define N(ary) (sizeof(ary) / sizeof(*ary))
|
2016-01-31 20:50:18 +01:00
|
|
|
#define STRING_SIZE(s) (L9P_WORD + (s != NULL ? (uint16_t)strlen(s) : 0))
|
2016-01-23 18:45:17 +01:00
|
|
|
#define QID_SIZE (L9P_BYTE + L9P_DWORD + L9P_QWORD)
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static int l9p_iov_io(struct l9p_message *, void *, size_t);
|
|
|
|
static inline int l9p_pu8(struct l9p_message *, uint8_t *);
|
|
|
|
static inline int l9p_pu16(struct l9p_message *, uint16_t *);
|
|
|
|
static inline int l9p_pu32(struct l9p_message *, uint32_t *);
|
|
|
|
static inline int l9p_pu64(struct l9p_message *, uint64_t *);
|
|
|
|
static int l9p_pustring(struct l9p_message *, char **s);
|
2016-01-31 01:56:11 +01:00
|
|
|
static int l9p_pustrings(struct l9p_message *, uint16_t *, char *[], size_t);
|
2016-01-28 00:40:43 +01:00
|
|
|
static int l9p_puqid(struct l9p_message *, struct l9p_qid *);
|
2016-01-31 01:56:11 +01:00
|
|
|
static int l9p_puqids(struct l9p_message *, uint16_t *, struct l9p_qid *q);
|
2016-01-23 18:45:17 +01:00
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static int
|
|
|
|
l9p_iov_io(struct l9p_message *msg, void *buffer, size_t len)
|
2016-01-23 18:45:17 +01:00
|
|
|
{
|
2016-01-31 01:56:11 +01:00
|
|
|
size_t done = 0;
|
|
|
|
size_t left = len;
|
|
|
|
|
|
|
|
assert(msg != NULL);
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
if (len == 0)
|
|
|
|
return (0);
|
2016-03-13 22:08:51 +01:00
|
|
|
|
|
|
|
if (msg->lm_estimate)
|
|
|
|
return ((int)len);
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
if (msg->lm_cursor_iov >= msg->lm_niov)
|
|
|
|
return (-1);
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
assert(buffer != NULL);
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
while (left > 0) {
|
|
|
|
size_t idx = msg->lm_cursor_iov;
|
|
|
|
size_t space = msg->lm_iov[idx].iov_len - msg->lm_cursor_offset;
|
|
|
|
size_t towrite = MIN(space, left);
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 20:50:18 +01:00
|
|
|
if (msg->lm_mode == L9P_PACK) {
|
|
|
|
memcpy((char *)msg->lm_iov[idx].iov_base +
|
|
|
|
msg->lm_cursor_offset, (char *)buffer + done,
|
|
|
|
towrite);
|
|
|
|
}
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 20:50:18 +01:00
|
|
|
if (msg->lm_mode == L9P_UNPACK) {
|
|
|
|
memcpy((char *)buffer + done,
|
|
|
|
(char *)msg->lm_iov[idx].iov_base +
|
|
|
|
msg->lm_cursor_offset, towrite);
|
|
|
|
}
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
msg->lm_cursor_offset += towrite;
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
if (space - towrite == 0) {
|
|
|
|
/* Advance to next iov */
|
|
|
|
msg->lm_cursor_iov++;
|
|
|
|
msg->lm_cursor_offset = 0;
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
if (msg->lm_cursor_iov > msg->lm_niov)
|
|
|
|
return (-1);
|
|
|
|
}
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
done += towrite;
|
|
|
|
left -= towrite;
|
|
|
|
}
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
msg->lm_size += done;
|
2016-01-31 20:50:18 +01:00
|
|
|
return ((int)done);
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static inline int
|
2016-01-23 18:45:17 +01:00
|
|
|
l9p_pu8(struct l9p_message *msg, uint8_t *val)
|
|
|
|
{
|
2016-01-28 15:18:55 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
return (l9p_iov_io(msg, val, sizeof (uint8_t)));
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static inline int
|
2016-01-23 18:45:17 +01:00
|
|
|
l9p_pu16(struct l9p_message *msg, uint16_t *val)
|
|
|
|
{
|
2016-01-28 15:18:55 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
return (l9p_iov_io(msg, val, sizeof (uint16_t)));
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static inline int
|
2016-01-23 18:45:17 +01:00
|
|
|
l9p_pu32(struct l9p_message *msg, uint32_t *val)
|
|
|
|
{
|
2016-01-28 15:18:55 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
return (l9p_iov_io(msg, val, sizeof (uint32_t)));
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static inline int
|
2016-01-23 18:45:17 +01:00
|
|
|
l9p_pu64(struct l9p_message *msg, uint64_t *val)
|
|
|
|
{
|
2016-01-28 15:18:55 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
return (l9p_iov_io(msg, val, sizeof (uint64_t)));
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static int
|
2016-01-23 18:45:17 +01:00
|
|
|
l9p_pustring(struct l9p_message *msg, char **s)
|
|
|
|
{
|
2016-01-31 01:56:11 +01:00
|
|
|
uint16_t len;
|
2016-01-23 18:45:17 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
if (msg->lm_mode == L9P_PACK)
|
2016-01-31 20:50:18 +01:00
|
|
|
len = *s != NULL ? (uint16_t)strlen(*s) : 0;
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
if (l9p_pu16(msg, &len) < 0)
|
|
|
|
return (-1);
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
if (msg->lm_mode == L9P_UNPACK)
|
|
|
|
*s = l9p_calloc(1, len + 1);
|
2016-01-28 15:18:55 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
if (l9p_iov_io(msg, *s, len) < 0)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
return (len + 2);
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static int
|
2016-01-23 18:45:17 +01:00
|
|
|
l9p_pustrings(struct l9p_message *msg, uint16_t *num, char *strings[],
|
|
|
|
size_t max)
|
|
|
|
{
|
2016-01-31 01:56:11 +01:00
|
|
|
size_t i;
|
|
|
|
int ret;
|
|
|
|
int r = 0;
|
2016-01-23 18:45:17 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
l9p_pu16(msg, num);
|
2016-01-23 18:45:17 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
for (i = 0; i < MIN(*num, max); i++) {
|
|
|
|
ret = l9p_pustring(msg, &strings[i]);
|
|
|
|
if (ret < 1)
|
|
|
|
return (-1);
|
2016-01-23 18:45:17 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
r += ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (r);
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static int
|
2016-01-23 18:45:17 +01:00
|
|
|
l9p_puqid(struct l9p_message *msg, struct l9p_qid *qid)
|
|
|
|
{
|
2016-01-31 01:56:11 +01:00
|
|
|
int r = 0;
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
r += l9p_pu8(msg, (uint8_t *) & qid->type);
|
|
|
|
r += l9p_pu32(msg, &qid->version);
|
|
|
|
r += l9p_pu64(msg, &qid->path);
|
2016-01-28 00:40:43 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
return (r);
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
static int
|
2016-01-31 01:56:11 +01:00
|
|
|
l9p_puqids(struct l9p_message *msg, uint16_t *num, struct l9p_qid *qids)
|
2016-01-23 18:45:17 +01:00
|
|
|
{
|
2016-01-31 01:56:11 +01:00
|
|
|
int i, ret, r = 0;
|
|
|
|
l9p_pu16(msg, num);
|
|
|
|
|
|
|
|
for (i = 0; i < *num; i++) {
|
|
|
|
ret = l9p_puqid(msg, &qids[i]);
|
|
|
|
if (ret < 0)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
r += ret;
|
|
|
|
}
|
2016-01-23 18:45:17 +01:00
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
return (r);
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-28 00:40:43 +01:00
|
|
|
int
|
2016-01-28 15:18:55 +01:00
|
|
|
l9p_pustat(struct l9p_message *msg, struct l9p_stat *stat,
|
|
|
|
enum l9p_version version)
|
2016-01-23 18:45:17 +01:00
|
|
|
{
|
2016-01-31 01:56:11 +01:00
|
|
|
int r = 0;
|
|
|
|
uint16_t size;
|
|
|
|
|
|
|
|
if (msg->lm_mode == L9P_PACK)
|
|
|
|
size = l9p_sizeof_stat(stat, version) - 2;
|
|
|
|
|
|
|
|
r += l9p_pu16(msg, &size);
|
|
|
|
r += l9p_pu16(msg, &stat->type);
|
|
|
|
r += l9p_pu32(msg, &stat->dev);
|
|
|
|
r += l9p_puqid(msg, &stat->qid);
|
|
|
|
r += l9p_pu32(msg, &stat->mode);
|
|
|
|
r += l9p_pu32(msg, &stat->atime);
|
|
|
|
r += l9p_pu32(msg, &stat->mtime);
|
|
|
|
r += l9p_pu64(msg, &stat->length);
|
|
|
|
r += l9p_pustring(msg, &stat->name);
|
|
|
|
r += l9p_pustring(msg, &stat->uid);
|
|
|
|
r += l9p_pustring(msg, &stat->gid);
|
|
|
|
r += l9p_pustring(msg, &stat->muid);
|
|
|
|
|
|
|
|
if (version == L9P_2000U) {
|
|
|
|
r += l9p_pustring(msg, &stat->extension);
|
|
|
|
r += l9p_pu32(msg, &stat->n_uid);
|
|
|
|
r += l9p_pu32(msg, &stat->n_gid);
|
|
|
|
r += l9p_pu32(msg, &stat->n_muid);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (r < size + 2)
|
|
|
|
return (-1);
|
|
|
|
|
|
|
|
return (r);
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
int
|
2016-01-28 15:18:55 +01:00
|
|
|
l9p_pufcall(struct l9p_message *msg, union l9p_fcall *fcall,
|
|
|
|
enum l9p_version version)
|
2016-01-23 18:45:17 +01:00
|
|
|
{
|
2016-01-31 01:56:11 +01:00
|
|
|
uint32_t length = 0;
|
|
|
|
|
|
|
|
l9p_pu32(msg, &length);
|
|
|
|
l9p_pu8(msg, &fcall->hdr.type);
|
|
|
|
l9p_pu16(msg, &fcall->hdr.tag);
|
|
|
|
|
|
|
|
switch (fcall->hdr.type) {
|
2016-03-13 22:08:51 +01:00
|
|
|
case L9P_TSTATFS:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RSTATFS:
|
|
|
|
l9p_pu32(msg, &fcall->rstatfs.type);
|
|
|
|
l9p_pu32(msg, &fcall->rstatfs.bsize);
|
|
|
|
l9p_pu64(msg, &fcall->rstatfs.blocks);
|
|
|
|
l9p_pu64(msg, &fcall->rstatfs.bfree);
|
|
|
|
l9p_pu64(msg, &fcall->rstatfs.bavail);
|
|
|
|
l9p_pu64(msg, &fcall->rstatfs.files);
|
|
|
|
l9p_pu64(msg, &fcall->rstatfs.ffree);
|
|
|
|
l9p_pu64(msg, &fcall->rstatfs.fsid);
|
|
|
|
l9p_pu32(msg, &fcall->rstatfs.namelen);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TLCREATE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RLCREATE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TSYMLINK:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pustring(msg, &fcall->tsymlink.name);
|
|
|
|
l9p_pustring(msg, &fcall->tsymlink.symtgt);
|
|
|
|
l9p_pu32(msg, &fcall->tsymlink.gid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RSYMLINK:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TMKNOD:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pustring(msg, &fcall->tmknod.name);
|
|
|
|
l9p_pu32(msg, &fcall->tmknod.mode);
|
|
|
|
l9p_pu32(msg, &fcall->tmknod.major);
|
|
|
|
l9p_pu32(msg, &fcall->tmknod.minor);
|
|
|
|
l9p_pu32(msg, &fcall->tmknod.gid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RMKNOD:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TRENAME:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu32(msg, &fcall->trename.dfid);
|
|
|
|
l9p_pustring(msg, &fcall->trename.name);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RRENAME:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TREADLINK:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RREADLINK:
|
|
|
|
l9p_pustring(msg, &fcall->rreadlink.target);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TGETATTR:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu64(msg, &fcall->tgetattr.request_mask);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RGETATTR:
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.valid);
|
|
|
|
l9p_puqid(msg, &fcall->rgetattr.qid);
|
|
|
|
l9p_pu32(msg, &fcall->rgetattr.mode);
|
|
|
|
l9p_pu32(msg, &fcall->rgetattr.uid);
|
|
|
|
l9p_pu32(msg, &fcall->rgetattr.gid);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.nlink);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.rdev);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.size);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.blksize);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.blocks);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.atime_sec);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.atime_nsec);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.mtime_sec);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.mtime_nsec);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.ctime_sec);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.ctime_nsec);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.btime_sec);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.btime_nsec);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.gen);
|
|
|
|
l9p_pu64(msg, &fcall->rgetattr.data_version);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TSETATTR:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu32(msg, &fcall->tsetattr.valid);
|
|
|
|
l9p_pu32(msg, &fcall->tsetattr.mode);
|
|
|
|
l9p_pu32(msg, &fcall->tsetattr.uid);
|
|
|
|
l9p_pu32(msg, &fcall->tsetattr.gid);
|
|
|
|
l9p_pu64(msg, &fcall->tsetattr.size);
|
|
|
|
l9p_pu64(msg, &fcall->tsetattr.atime_sec);
|
|
|
|
l9p_pu64(msg, &fcall->tsetattr.atime_nsec);
|
|
|
|
l9p_pu64(msg, &fcall->tsetattr.mtime_sec);
|
|
|
|
l9p_pu64(msg, &fcall->tsetattr.mtime_nsec);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RSETATTR:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TXATTRWALK:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu32(msg, &fcall->txattrwalk.newfid);
|
|
|
|
l9p_pustring(msg, &fcall->txattrwalk.name);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RXATTRWALK:
|
|
|
|
l9p_pu64(msg, &fcall->rxattrwalk.size);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TXATTRCREATE:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pustring(msg, &fcall->txattrcreate.name);
|
|
|
|
l9p_pu64(msg, &fcall->txattrcreate.attr_size);
|
|
|
|
l9p_pu32(msg, &fcall->txattrcreate.flags);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RXATTRCREATE:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TREADDIR:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu64(msg, &fcall->io.offset);
|
|
|
|
l9p_pu32(msg, &fcall->io.count);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RREADDIR:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TFSYNC:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RFSYNC:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TLOCK:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu8(msg, &fcall->tlock.type);
|
|
|
|
l9p_pu32(msg, &fcall->tlock.flags);
|
|
|
|
l9p_pu64(msg, &fcall->tlock.start);
|
|
|
|
l9p_pu64(msg, &fcall->tlock.length);
|
|
|
|
l9p_pu32(msg, &fcall->tlock.proc_id);
|
|
|
|
l9p_pustring(msg, &fcall->tlock.client_id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RLOCK:
|
|
|
|
l9p_pu8(msg, &fcall->rlock.status);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TGETLOCK:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu8(msg, &fcall->tlock.type);
|
|
|
|
l9p_pu32(msg, &fcall->tlock.flags);
|
|
|
|
l9p_pu64(msg, &fcall->tlock.start);
|
|
|
|
l9p_pu64(msg, &fcall->tlock.length);
|
|
|
|
l9p_pu32(msg, &fcall->tlock.proc_id);
|
|
|
|
l9p_pustring(msg, &fcall->tlock.client_id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RGETLOCK:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu8(msg, &fcall->rlock.type);
|
|
|
|
l9p_pu32(msg, &fcall->rlock.flags);
|
|
|
|
l9p_pu64(msg, &fcall->rlock.start);
|
|
|
|
l9p_pu64(msg, &fcall->rlock.length);
|
|
|
|
l9p_pu32(msg, &fcall->rlock.proc_id);
|
|
|
|
l9p_pustring(msg, &fcall->rlock.client_id);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TLINK:
|
|
|
|
l9p_pu32(msg, &fcall->tlink.dfid);
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pustring(msg, &fcall->tlink.name);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RLINK:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TMKDIR:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pustring(msg, &fcall->tmkdir.name);
|
|
|
|
l9p_pu32(msg, &fcall->tmkdir.mode);
|
|
|
|
l9p_pu32(msg, &fcall->tmkdir.gid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RMKDIR:
|
|
|
|
l9p_puqid(msg, &fcall->rmkdir.qid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TRENAMEAT:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pustring(msg, &fcall->trenameat.oldname);
|
|
|
|
l9p_pu32(msg, &fcall->trenameat.newdirfid);
|
|
|
|
l9p_pustring(msg, &fcall->trenameat.newname);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RRENAMEAT:
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TUNLINKAT:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pustring(msg, &fcall->tunlinkat.name);
|
|
|
|
l9p_pu32(msg, &fcall->tunlinkat.flags);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RUNLINKAT:
|
|
|
|
break;
|
|
|
|
|
2016-01-31 01:56:11 +01:00
|
|
|
case L9P_TVERSION:
|
|
|
|
case L9P_RVERSION:
|
|
|
|
l9p_pu32(msg, &fcall->version.msize);
|
|
|
|
l9p_pustring(msg, &fcall->version.version);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TAUTH:
|
|
|
|
l9p_pu32(msg, &fcall->tauth.afid);
|
|
|
|
l9p_pustring(msg, &fcall->tauth.uname);
|
|
|
|
l9p_pustring(msg, &fcall->tauth.aname);
|
|
|
|
if (version == L9P_2000U)
|
|
|
|
l9p_pu32(msg, &fcall->tauth.n_uname);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RAUTH:
|
|
|
|
l9p_puqid(msg, &fcall->rauth.aqid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RATTACH:
|
|
|
|
l9p_puqid(msg, &fcall->rattach.qid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TATTACH:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu32(msg, &fcall->tattach.afid);
|
|
|
|
l9p_pustring(msg, &fcall->tattach.uname);
|
|
|
|
l9p_pustring(msg, &fcall->tattach.aname);
|
|
|
|
if (version == L9P_2000U)
|
|
|
|
l9p_pu32(msg, &fcall->tattach.n_uname);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RERROR:
|
|
|
|
l9p_pustring(msg, &fcall->error.ename);
|
|
|
|
if (version == L9P_2000U)
|
|
|
|
l9p_pu32(msg, &fcall->error.errnum);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TFLUSH:
|
|
|
|
l9p_pu16(msg, &fcall->tflush.oldtag);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TWALK:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu32(msg, &fcall->twalk.newfid);
|
|
|
|
l9p_pustrings(msg, &fcall->twalk.nwname,
|
|
|
|
fcall->twalk.wname, N(fcall->twalk.wname));
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RWALK:
|
|
|
|
l9p_puqids(msg, &fcall->rwalk.nwqid, fcall->rwalk.wqid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TOPEN:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu8(msg, &fcall->topen.mode);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_ROPEN:
|
|
|
|
case L9P_RCREATE:
|
|
|
|
l9p_puqid(msg, &fcall->ropen.qid);
|
|
|
|
l9p_pu32(msg, &fcall->ropen.iounit);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TCREATE:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pustring(msg, &fcall->tcreate.name);
|
|
|
|
l9p_pu32(msg, &fcall->tcreate.perm);
|
|
|
|
l9p_pu8(msg, &fcall->tcreate.mode);
|
|
|
|
if (version == L9P_2000U)
|
|
|
|
l9p_pustring(msg, &fcall->tcreate.extension);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TREAD:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu64(msg, &fcall->io.offset);
|
|
|
|
l9p_pu32(msg, &fcall->io.count);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RREAD:
|
|
|
|
l9p_pu32(msg, &fcall->io.count);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TWRITE:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu64(msg, &fcall->io.offset);
|
|
|
|
l9p_pu32(msg, &fcall->io.count);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RWRITE:
|
|
|
|
l9p_pu32(msg, &fcall->io.count);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TCLUNK:
|
|
|
|
case L9P_TSTAT:
|
|
|
|
case L9P_TREMOVE:
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_RSTAT:
|
|
|
|
{
|
|
|
|
uint16_t size = l9p_sizeof_stat(&fcall->rstat.stat,
|
|
|
|
version);
|
|
|
|
l9p_pu16(msg, &size);
|
|
|
|
l9p_pustat(msg, &fcall->rstat.stat, version);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
|
|
|
|
case L9P_TWSTAT:
|
|
|
|
{
|
|
|
|
uint16_t size;
|
|
|
|
l9p_pu32(msg, &fcall->hdr.fid);
|
|
|
|
l9p_pu16(msg, &size);
|
|
|
|
l9p_pustat(msg, &fcall->twstat.stat, version);
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (msg->lm_mode == L9P_PACK) {
|
|
|
|
/* Rewind to the beginning */
|
2016-01-31 20:50:18 +01:00
|
|
|
uint32_t len = (uint32_t)msg->lm_size;
|
2016-01-31 01:56:11 +01:00
|
|
|
msg->lm_cursor_offset = 0;
|
|
|
|
msg->lm_cursor_iov = 0;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Subtract 4 bytes from message size, becase we're
|
|
|
|
* overwriting size (rewinding message to the beginning)
|
|
|
|
* and writing again.
|
|
|
|
*/
|
|
|
|
msg->lm_size -= sizeof (uint32_t);
|
|
|
|
|
|
|
|
if (fcall->hdr.type == L9P_RREAD)
|
|
|
|
len += fcall->io.count;
|
|
|
|
|
|
|
|
l9p_pu32(msg, &len);
|
|
|
|
}
|
|
|
|
|
|
|
|
return (0);
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|
|
|
|
|
2016-01-31 20:50:18 +01:00
|
|
|
void
|
|
|
|
l9p_freefcall(union l9p_fcall *fcall)
|
|
|
|
{
|
|
|
|
uint16_t i;
|
|
|
|
|
|
|
|
switch (fcall->hdr.type) {
|
|
|
|
case L9P_TVERSION:
|
|
|
|
case L9P_RVERSION:
|
|
|
|
free(fcall->version.version);
|
|
|
|
return;
|
|
|
|
case L9P_TATTACH:
|
|
|
|
free(fcall->tattach.aname);
|
|
|
|
free(fcall->tattach.uname);
|
|
|
|
return;
|
|
|
|
case L9P_TWALK:
|
|
|
|
for (i = 0; i < fcall->twalk.nwname; i++)
|
|
|
|
free(fcall->twalk.wname[i]);
|
|
|
|
return;
|
|
|
|
case L9P_TCREATE:
|
|
|
|
case L9P_TOPEN:
|
|
|
|
free(fcall->tcreate.name);
|
|
|
|
free(fcall->tcreate.extension);
|
|
|
|
return;
|
|
|
|
case L9P_RSTAT:
|
|
|
|
l9p_freestat(&fcall->rstat.stat);
|
|
|
|
return;
|
|
|
|
case L9P_TWSTAT:
|
|
|
|
l9p_freestat(&fcall->twstat.stat);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void
|
|
|
|
l9p_freestat(struct l9p_stat *stat)
|
|
|
|
{
|
|
|
|
free(stat->name);
|
|
|
|
free(stat->extension);
|
|
|
|
free(stat->uid);
|
|
|
|
free(stat->gid);
|
|
|
|
free(stat->muid);
|
|
|
|
}
|
|
|
|
|
2016-01-23 22:57:40 +01:00
|
|
|
uint16_t
|
2016-01-28 15:18:55 +01:00
|
|
|
l9p_sizeof_stat(struct l9p_stat *stat, enum l9p_version version)
|
|
|
|
{
|
2016-01-31 01:56:11 +01:00
|
|
|
uint16_t size = L9P_WORD /* size */
|
|
|
|
+ L9P_WORD /* type */
|
|
|
|
+ L9P_DWORD /* dev */
|
|
|
|
+ QID_SIZE /* qid */
|
|
|
|
+ 3 * L9P_DWORD /* mode, atime, mtime */
|
|
|
|
+ L9P_QWORD /* length */
|
|
|
|
+ STRING_SIZE(stat->name)
|
|
|
|
+ STRING_SIZE(stat->uid)
|
|
|
|
+ STRING_SIZE(stat->gid)
|
|
|
|
+ STRING_SIZE(stat->muid);
|
|
|
|
|
|
|
|
if (version == L9P_2000U) {
|
|
|
|
size += STRING_SIZE(stat->extension)
|
|
|
|
+ 3 * L9P_DWORD;
|
|
|
|
}
|
|
|
|
|
|
|
|
return (size);
|
2016-01-23 18:45:17 +01:00
|
|
|
}
|