int p9dirent_read(struct p9_client *clnt, char *buf, int len,
		  struct p9_dirent *dirent)
{
	struct p9_fcall fake_pdu;
	int ret;
	char *nameptr;

	fake_pdu.size = len;
	fake_pdu.capacity = len;
	fake_pdu.sdata = buf;
	fake_pdu.offset = 0;

	ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "Qqbs", &dirent->qid,
			  &dirent->d_off, &dirent->d_type, &nameptr);
	if (ret) {
		p9_debug(P9_DEBUG_9P, "<<< p9dirent_read failed: %d\n", ret);
		trace_9p_protocol_dump(clnt, &fake_pdu);
		goto out;
	}

	strcpy(dirent->d_name, nameptr);
	kfree(nameptr);

out:
	return fake_pdu.offset;
}
Esempio n. 2
0
int
p9_client_read(struct p9_fid *fid, char *data, char __user *udata, u64 offset,
								u32 count)
{
	int err, rsize, total;
	struct p9_client *clnt;
	struct p9_req_t *req;
	char *dataptr;

	P9_DPRINTK(P9_DEBUG_9P, ">>> TREAD fid %d offset %llu %d\n", fid->fid,
					(long long unsigned) offset, count);
	err = 0;
	clnt = fid->clnt;
	total = 0;

	rsize = fid->iounit;
	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
		rsize = clnt->msize - P9_IOHDRSZ;

	if (count < rsize)
		rsize = count;

	req = p9_client_rpc(clnt, P9_TREAD, "dqd", fid->fid, offset, rsize);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->dotu, "D", &count, &dataptr);
	if (err) {
		p9pdu_dump(1, req->rc);
		goto free_and_error;
	}

	P9_DPRINTK(P9_DEBUG_9P, "<<< RREAD count %d\n", count);

	if (data) {
		memmove(data, dataptr, count);
		data += count;
	}

	if (udata) {
		err = copy_to_user(udata, dataptr, count);
		if (err) {
			err = -EFAULT;
			goto free_and_error;
		}
	}

	p9_free_req(clnt, req);
	return count;

free_and_error:
	p9_free_req(clnt, req);
error:
	return err;
}
Esempio n. 3
0
struct p9_fid *p9_client_attach(struct p9_client *clnt, struct p9_fid *afid,
	char *uname, u32 n_uname, char *aname)
{
	int err;
	struct p9_req_t *req;
	struct p9_fid *fid;
	struct p9_qid qid;

	P9_DPRINTK(P9_DEBUG_9P, ">>> TATTACH afid %d uname %s aname %s\n",
					afid ? afid->fid : -1, uname, aname);
	err = 0;

	fid = p9_fid_create(clnt);
	if (IS_ERR(fid)) {
		err = PTR_ERR(fid);
		fid = NULL;
		goto error;
	}

	req = p9_client_rpc(clnt, P9_TATTACH, "ddss?d", fid->fid,
			afid ? afid->fid : P9_NOFID, uname, aname, n_uname);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->dotu, "Q", &qid);
	if (err) {
		p9pdu_dump(1, req->rc);
		p9_free_req(clnt, req);
		goto error;
	}

	P9_DPRINTK(P9_DEBUG_9P, "<<< RATTACH qid %x.%llx.%x\n",
					qid.type,
					(unsigned long long)qid.path,
					qid.version);

	memmove(&fid->qid, &qid, sizeof(struct p9_qid));

	p9_free_req(clnt, req);
	return fid;

error:
	if (fid)
		p9_fid_destroy(fid);
	return ERR_PTR(err);
}
Esempio n. 4
0
int
p9_client_write(struct p9_fid *fid, char *data, const char __user *udata,
							u64 offset, u32 count)
{
	int err, rsize, total;
	struct p9_client *clnt;
	struct p9_req_t *req;

	P9_DPRINTK(P9_DEBUG_9P, ">>> TWRITE fid %d offset %llu count %d\n",
				fid->fid, (long long unsigned) offset, count);
	err = 0;
	clnt = fid->clnt;
	total = 0;

	rsize = fid->iounit;
	if (!rsize || rsize > clnt->msize-P9_IOHDRSZ)
		rsize = clnt->msize - P9_IOHDRSZ;

	if (count < rsize)
		rsize = count;
	if (data)
		req = p9_client_rpc(clnt, P9_TWRITE, "dqD", fid->fid, offset,
								rsize, data);
	else
		req = p9_client_rpc(clnt, P9_TWRITE, "dqU", fid->fid, offset,
								rsize, udata);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->dotu, "d", &count);
	if (err) {
		p9pdu_dump(1, req->rc);
		goto free_and_error;
	}

	P9_DPRINTK(P9_DEBUG_9P, "<<< RWRITE count %d\n", count);

	p9_free_req(clnt, req);
	return count;

free_and_error:
	p9_free_req(clnt, req);
error:
	return err;
}
Esempio n. 5
0
struct p9_wstat *p9_client_stat(struct p9_fid *fid)
{
	int err;
	struct p9_client *clnt;
	struct p9_wstat *ret = kmalloc(sizeof(struct p9_wstat), GFP_KERNEL);
	struct p9_req_t *req;
	u16 ignored;

	P9_DPRINTK(P9_DEBUG_9P, ">>> TSTAT fid %d\n", fid->fid);

	if (!ret)
		return ERR_PTR(-ENOMEM);

	err = 0;
	clnt = fid->clnt;

	req = p9_client_rpc(clnt, P9_TSTAT, "d", fid->fid);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->dotu, "wS", &ignored, ret);
	if (err) {
		p9pdu_dump(1, req->rc);
		p9_free_req(clnt, req);
		goto error;
	}

	P9_DPRINTK(P9_DEBUG_9P,
		"<<< RSTAT sz=%x type=%x dev=%x qid=%x.%llx.%x\n"
		"<<<    mode=%8.8x atime=%8.8x mtime=%8.8x length=%llx\n"
		"<<<    name=%s uid=%s gid=%s muid=%s extension=(%s)\n"
		"<<<    uid=%d gid=%d n_muid=%d\n",
		ret->size, ret->type, ret->dev, ret->qid.type,
		(unsigned long long)ret->qid.path, ret->qid.version, ret->mode,
		ret->atime, ret->mtime, (unsigned long long)ret->length,
		ret->name, ret->uid, ret->gid, ret->muid, ret->extension,
		ret->n_uid, ret->n_gid, ret->n_muid);

	p9_free_req(clnt, req);
	return ret;

error:
	kfree(ret);
	return ERR_PTR(err);
}
Esempio n. 6
0
int p9stat_read(char *buf, int len, struct p9_wstat *st, int proto_version)
{
    struct p9_fcall fake_pdu;
    int ret;

    fake_pdu.size = len;
    fake_pdu.capacity = len;
    fake_pdu.sdata = buf;
    fake_pdu.offset = 0;

    ret = p9pdu_readf(&fake_pdu, proto_version, "S", st);
    if (ret) {
        P9_DPRINTK(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret);
        p9pdu_dump(1, &fake_pdu);
    }

    return ret;
}
int p9stat_read(struct p9_client *clnt, char *buf, int len, struct p9_wstat *st)
{
	struct p9_fcall fake_pdu;
	int ret;

	fake_pdu.size = len;
	fake_pdu.capacity = len;
	fake_pdu.sdata = buf;
	fake_pdu.offset = 0;

	ret = p9pdu_readf(&fake_pdu, clnt->proto_version, "S", st);
	if (ret) {
		p9_debug(P9_DEBUG_9P, "<<< p9stat_read failed: %d\n", ret);
		trace_9p_protocol_dump(clnt, &fake_pdu);
	}

	return ret;
}
Esempio n. 8
0
int p9_client_fcreate(struct p9_fid *fid, char *name, u32 perm, int mode,
		     char *extension)
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;
	struct p9_qid qid;
	int iounit;

	P9_DPRINTK(P9_DEBUG_9P, ">>> TCREATE fid %d name %s perm %d mode %d\n",
						fid->fid, name, perm, mode);
	err = 0;
	clnt = fid->clnt;

	if (fid->mode != -1)
		return -EINVAL;

	req = p9_client_rpc(clnt, P9_TCREATE, "dsdb?s", fid->fid, name, perm,
				mode, extension);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
	if (err) {
		p9pdu_dump(1, req->rc);
		goto free_and_error;
	}

	P9_DPRINTK(P9_DEBUG_9P, "<<< RCREATE qid %x.%llx.%x iounit %x\n",
				qid.type,
				(unsigned long long)qid.path,
				qid.version, iounit);

	fid->mode = mode;
	fid->iounit = iounit;

free_and_error:
	p9_free_req(clnt, req);
error:
	return err;
}
Esempio n. 9
0
static int p9_check_errors(struct p9_client *c, struct p9_req_t *req)
{
	int8_t type;
	int err;

	err = p9_parse_header(req->rc, NULL, &type, NULL, 0);
	if (err) {
		P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse header %d\n", err);
		return err;
	}

	if (type == P9_RERROR) {
		int ecode;
		char *ename;

		err = p9pdu_readf(req->rc, c->dotu, "s?d", &ename, &ecode);
		if (err) {
			P9_DPRINTK(P9_DEBUG_ERROR, "couldn't parse error%d\n",
									err);
			return err;
		}

		if (c->dotu)
			err = -ecode;

		if (!err) {
			err = p9_errstr2errno(ename, strlen(ename));

			/* string match failed */
			if (!err)
				err = -ESERVERFAULT;
		}

		P9_DPRINTK(P9_DEBUG_9P, "<<< RERROR (%d) %s\n", -ecode, ename);

		kfree(ename);
	} else
		err = 0;

	return err;
}
Esempio n. 10
0
int p9_client_version(struct p9_client *c)
{
	int err = 0;
	struct p9_req_t *req;
	char *version;
	int msize;

	P9_DPRINTK(P9_DEBUG_9P, ">>> TVERSION msize %d extended %d\n",
							c->msize, c->dotu);
	req = p9_client_rpc(c, P9_TVERSION, "ds", c->msize,
				c->dotu ? "9P2000.u" : "9P2000");
	if (IS_ERR(req))
		return PTR_ERR(req);

	err = p9pdu_readf(req->rc, c->dotu, "ds", &msize, &version);
	if (err) {
		P9_DPRINTK(P9_DEBUG_9P, "version error %d\n", err);
		p9pdu_dump(1, req->rc);
		goto error;
	}

	P9_DPRINTK(P9_DEBUG_9P, "<<< RVERSION msize %d %s\n", msize, version);
	if (!memcmp(version, "9P2000.u", 8))
		c->dotu = 1;
	else if (!memcmp(version, "9P2000", 6))
		c->dotu = 0;
	else {
		err = -EREMOTEIO;
		goto error;
	}

	if (msize < c->msize)
		c->msize = msize;

error:
	kfree(version);
	p9_free_req(c, req);

	return err;
}
Esempio n. 11
0
int p9_client_open(struct p9_fid *fid, int mode)
{
	int err;
	struct p9_client *clnt;
	struct p9_req_t *req;
	struct p9_qid qid;
	int iounit;

	P9_DPRINTK(P9_DEBUG_9P, ">>> TOPEN fid %d mode %d\n", fid->fid, mode);
	err = 0;
	clnt = fid->clnt;

	if (fid->mode != -1)
		return -EINVAL;

	req = p9_client_rpc(clnt, P9_TOPEN, "db", fid->fid, mode);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->dotu, "Qd", &qid, &iounit);
	if (err) {
		p9pdu_dump(1, req->rc);
		goto free_and_error;
	}

	P9_DPRINTK(P9_DEBUG_9P, "<<< ROPEN qid %x.%llx.%x iounit %x\n",
				qid.type,
				(unsigned long long)qid.path,
				qid.version, iounit);

	fid->mode = mode;
	fid->iounit = iounit;

free_and_error:
	p9_free_req(clnt, req);
error:
	return err;
}
Esempio n. 12
0
int
p9_parse_header(struct p9_fcall *pdu, int32_t *size, int8_t *type, int16_t *tag,
								int rewind)
{
	int8_t r_type;
	int16_t r_tag;
	int32_t r_size;
	int offset = pdu->offset;
	int err;

	pdu->offset = 0;
	if (pdu->size == 0)
		pdu->size = 7;

	err = p9pdu_readf(pdu, 0, "dbw", &r_size, &r_type, &r_tag);
	if (err)
		goto rewind_and_exit;

	pdu->size = r_size;
	pdu->id = r_type;
	pdu->tag = r_tag;

	P9_DPRINTK(P9_DEBUG_9P, "<<< size=%d type: %d tag: %d\n", pdu->size,
							pdu->id, pdu->tag);

	if (type)
		*type = r_type;
	if (tag)
		*tag = r_tag;
	if (size)
		*size = r_size;


rewind_and_exit:
	if (rewind)
		pdu->offset = offset;
	return err;
}
Esempio n. 13
0
static int
p9pdu_vreadf(struct p9_fcall *pdu, int proto_version, const char *fmt,
             va_list ap)
{
    const char *ptr;
    int errcode = 0;

    for (ptr = fmt; *ptr; ptr++) {
        switch (*ptr) {
        case 'b': {
            int8_t *val = va_arg(ap, int8_t *);
            if (pdu_read(pdu, val, sizeof(*val))) {
                errcode = -EFAULT;
                break;
            }
        }
        break;
        case 'w': {
            int16_t *val = va_arg(ap, int16_t *);
            __le16 le_val;
            if (pdu_read(pdu, &le_val, sizeof(le_val))) {
                errcode = -EFAULT;
                break;
            }
            *val = le16_to_cpu(le_val);
        }
        break;
        case 'd': {
            int32_t *val = va_arg(ap, int32_t *);
            __le32 le_val;
            if (pdu_read(pdu, &le_val, sizeof(le_val))) {
                errcode = -EFAULT;
                break;
            }
            *val = le32_to_cpu(le_val);
        }
        break;
        case 'q': {
            int64_t *val = va_arg(ap, int64_t *);
            __le64 le_val;
            if (pdu_read(pdu, &le_val, sizeof(le_val))) {
                errcode = -EFAULT;
                break;
            }
            *val = le64_to_cpu(le_val);
        }
        break;
        case 's': {
            char **sptr = va_arg(ap, char **);
            int16_t len;
            int size;

            errcode = p9pdu_readf(pdu, proto_version,
                                  "w", &len);
            if (errcode)
                break;

            size = MAX(len, 0);

            *sptr = kmalloc(size + 1, GFP_KERNEL);
            if (*sptr == NULL) {
                errcode = -EFAULT;
                break;
            }
            if (pdu_read(pdu, *sptr, size)) {
                errcode = -EFAULT;
                kfree(*sptr);
                *sptr = NULL;
            } else
                (*sptr)[size] = 0;
        }
        break;
        case 'Q': {
            struct p9_qid *qid =
                va_arg(ap, struct p9_qid *);

            errcode = p9pdu_readf(pdu, proto_version, "bdq",
                                  &qid->type, &qid->version,
                                  &qid->path);
        }
        break;
        case 'S': {
            struct p9_wstat *stbuf =
                va_arg(ap, struct p9_wstat *);

            memset(stbuf, 0, sizeof(struct p9_wstat));
            stbuf->n_uid = stbuf->n_gid = stbuf->n_muid =
                                              -1;
            errcode =
                p9pdu_readf(pdu, proto_version,
                            "wwdQdddqssss?sddd",
                            &stbuf->size, &stbuf->type,
                            &stbuf->dev, &stbuf->qid,
                            &stbuf->mode, &stbuf->atime,
                            &stbuf->mtime, &stbuf->length,
                            &stbuf->name, &stbuf->uid,
                            &stbuf->gid, &stbuf->muid,
                            &stbuf->extension,
                            &stbuf->n_uid, &stbuf->n_gid,
                            &stbuf->n_muid);
            if (errcode)
                p9stat_free(stbuf);
        }
        break;
        case 'D': {
            int32_t *count = va_arg(ap, int32_t *);
            void **data = va_arg(ap, void **);

            errcode =
                p9pdu_readf(pdu, proto_version, "d", count);
            if (!errcode) {
                *count =
                    MIN(*count,
                        pdu->size - pdu->offset);
                *data = &pdu->sdata[pdu->offset];
            }
        }
        break;
        case 'T': {
            int16_t *nwname = va_arg(ap, int16_t *);
            char ***wnames = va_arg(ap, char ***);

            errcode = p9pdu_readf(pdu, proto_version,
                                  "w", nwname);
            if (!errcode) {
                *wnames =
                    kmalloc(sizeof(char *) * *nwname,
                            GFP_KERNEL);
                if (!*wnames)
                    errcode = -ENOMEM;
            }

            if (!errcode) {
                int i;

                for (i = 0; i < *nwname; i++) {
                    errcode =
                        p9pdu_readf(pdu,
                                    proto_version,
                                    "s",
                                    &(*wnames)[i]);
                    if (errcode)
                        break;
                }
            }

            if (errcode) {
                if (*wnames) {
                    int i;

                    for (i = 0; i < *nwname; i++)
                        kfree((*wnames)[i]);
                }
                kfree(*wnames);
                *wnames = NULL;
            }
        }
        break;
        case 'R': {
            int16_t *nwqid = va_arg(ap, int16_t *);
            struct p9_qid **wqids =
                va_arg(ap, struct p9_qid **);

            *wqids = NULL;

            errcode =
                p9pdu_readf(pdu, proto_version, "w", nwqid);
            if (!errcode) {
                *wqids =
                    kmalloc(*nwqid *
                            sizeof(struct p9_qid),
                            GFP_KERNEL);
                if (*wqids == NULL)
                    errcode = -ENOMEM;
            }

            if (!errcode) {
                int i;

                for (i = 0; i < *nwqid; i++) {
                    errcode =
                        p9pdu_readf(pdu,
                                    proto_version,
                                    "Q",
                                    &(*wqids)[i]);
                    if (errcode)
                        break;
                }
            }

            if (errcode) {
                kfree(*wqids);
                *wqids = NULL;
            }
        }
        break;
        case '?':
            if ((proto_version != p9_proto_2000u) &&
                    (proto_version != p9_proto_2000L))
                return 0;
            break;
        default:
            BUG();
            break;
        }

        if (errcode)
            break;
    }

    return errcode;
}
Esempio n. 14
0
struct p9_fid *p9_client_walk(struct p9_fid *oldfid, int nwname, char **wnames,
	int clone)
{
	int err;
	struct p9_client *clnt;
	struct p9_fid *fid;
	struct p9_qid *wqids;
	struct p9_req_t *req;
	int16_t nwqids, count;

	err = 0;
	clnt = oldfid->clnt;
	if (clone) {
		fid = p9_fid_create(clnt);
		if (IS_ERR(fid)) {
			err = PTR_ERR(fid);
			fid = NULL;
			goto error;
		}

		fid->uid = oldfid->uid;
	} else
		fid = oldfid;


	P9_DPRINTK(P9_DEBUG_9P, ">>> TWALK fids %d,%d nwname %d wname[0] %s\n",
		oldfid->fid, fid->fid, nwname, wnames ? wnames[0] : NULL);

	req = p9_client_rpc(clnt, P9_TWALK, "ddT", oldfid->fid, fid->fid,
								nwname, wnames);
	if (IS_ERR(req)) {
		err = PTR_ERR(req);
		goto error;
	}

	err = p9pdu_readf(req->rc, clnt->dotu, "R", &nwqids, &wqids);
	if (err) {
		p9pdu_dump(1, req->rc);
		p9_free_req(clnt, req);
		goto clunk_fid;
	}
	p9_free_req(clnt, req);

	P9_DPRINTK(P9_DEBUG_9P, "<<< RWALK nwqid %d:\n", nwqids);

	if (nwqids != nwname) {
		err = -ENOENT;
		goto clunk_fid;
	}

	for (count = 0; count < nwqids; count++)
		P9_DPRINTK(P9_DEBUG_9P, "<<<     [%d] %x.%llx.%x\n",
			count, wqids[count].type, wqids[count].path,
			wqids[count].version);

	if (nwname)
		memmove(&fid->qid, &wqids[nwqids - 1], sizeof(struct p9_qid));
	else
		fid->qid = oldfid->qid;

	return fid;

clunk_fid:
	p9_client_clunk(fid);
	fid = NULL;

error:
	if (fid && (fid != oldfid))
		p9_fid_destroy(fid);

	return ERR_PTR(err);
}