Home | History | Annotate | Line # | Download | only in mount_psshfs
fs.c revision 1.24.42.1
      1  1.24.42.1  martin /*	$NetBSD: fs.c,v 1.24.42.1 2020/04/13 08:05:56 martin Exp $	*/
      2        1.1   pooka 
      3        1.1   pooka /*
      4       1.20   pooka  * Copyright (c) 2006-2009  Antti Kantee.  All Rights Reserved.
      5        1.1   pooka  *
      6        1.1   pooka  * Redistribution and use in source and binary forms, with or without
      7        1.1   pooka  * modification, are permitted provided that the following conditions
      8        1.1   pooka  * are met:
      9        1.1   pooka  * 1. Redistributions of source code must retain the above copyright
     10        1.1   pooka  *    notice, this list of conditions and the following disclaimer.
     11        1.1   pooka  * 2. Redistributions in binary form must reproduce the above copyright
     12        1.1   pooka  *    notice, this list of conditions and the following disclaimer in the
     13        1.1   pooka  *    documentation and/or other materials provided with the distribution.
     14        1.1   pooka  *
     15        1.1   pooka  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS
     16        1.1   pooka  * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
     17        1.1   pooka  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
     18        1.1   pooka  * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
     19        1.1   pooka  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
     20        1.1   pooka  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
     21        1.1   pooka  * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     22        1.1   pooka  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     23        1.1   pooka  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
     24        1.1   pooka  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
     25        1.1   pooka  * SUCH DAMAGE.
     26        1.1   pooka  */
     27        1.1   pooka 
     28        1.1   pooka #include <sys/cdefs.h>
     29        1.1   pooka #ifndef lint
     30  1.24.42.1  martin __RCSID("$NetBSD: fs.c,v 1.24.42.1 2020/04/13 08:05:56 martin Exp $");
     31        1.1   pooka #endif /* !lint */
     32        1.1   pooka 
     33        1.1   pooka #include <err.h>
     34        1.5   pooka #include <errno.h>
     35        1.1   pooka #include <puffs.h>
     36        1.1   pooka #include <signal.h>
     37        1.1   pooka #include <stdio.h>
     38        1.1   pooka #include <stdlib.h>
     39        1.1   pooka #include <unistd.h>
     40        1.1   pooka 
     41        1.1   pooka #include "psshfs.h"
     42        1.1   pooka #include "sftp_proto.h"
     43        1.1   pooka 
     44        1.8   pooka #define DO_IO(fname, a1, a2, a3, a4, rv)				\
     45       1.17   pooka do {									\
     46        1.8   pooka 	puffs_framebuf_seekset(a2, 0);					\
     47        1.8   pooka 	*(a4) = 0;							\
     48        1.8   pooka 	rv = fname(a1, a2, a3, a4);					\
     49       1.24     mrg 	if (rv) {							\
     50       1.17   pooka 		return rv ? rv : EPROTO;				\
     51       1.17   pooka 	}								\
     52       1.17   pooka } while (/*CONSTCOND*/0)
     53       1.17   pooka 
     54       1.17   pooka #define reterr(str, rv)							\
     55       1.17   pooka do {									\
     56       1.17   pooka 	fprintf str;							\
     57       1.17   pooka 	return rv;							\
     58       1.17   pooka } while (/*CONSTCOND*/0)
     59        1.8   pooka 
     60       1.18   pooka /* openssh extensions */
     61       1.18   pooka static const struct extunit {
     62       1.18   pooka 	const char *ext;
     63       1.18   pooka 	const char *val;
     64       1.18   pooka 	int extflag;
     65       1.18   pooka } exttable[] = {
     66       1.18   pooka {
     67       1.18   pooka 	"posix-rename (at) openssh.com",
     68       1.18   pooka 	"1",
     69       1.18   pooka 	SFTP_EXT_POSIX_RENAME,
     70       1.18   pooka },{
     71       1.18   pooka 	"statvfs (at) openssh.com",
     72       1.18   pooka 	"2",
     73       1.18   pooka 	SFTP_EXT_STATVFS,
     74       1.18   pooka },{
     75       1.18   pooka 	"fstatvfs (at) openssh.com",
     76       1.18   pooka 	"2",
     77       1.18   pooka 	SFTP_EXT_FSTATVFS,
     78       1.18   pooka },{
     79       1.18   pooka 	NULL,
     80       1.18   pooka 	NULL,
     81       1.18   pooka 	0
     82       1.18   pooka }};
     83       1.23   pooka 
     84        1.1   pooka int
     85       1.19   pooka psshfs_handshake(struct puffs_usermount *pu, int fd)
     86        1.1   pooka {
     87        1.4   pooka 	struct psshfs_ctx *pctx = puffs_getspecific(pu);
     88       1.17   pooka 	struct puffs_framebuf *pb;
     89        1.3   pooka 	struct puffs_pathobj *po_root;
     90        1.4   pooka 	struct puffs_node *pn_root;
     91       1.17   pooka 	struct vattr va, *rva;
     92       1.18   pooka 	const struct extunit *extu;
     93        1.1   pooka 	char *rootpath;
     94       1.18   pooka 	char *ext, *val;
     95        1.1   pooka 	uint32_t count;
     96        1.8   pooka 	int rv, done;
     97        1.1   pooka 
     98        1.8   pooka 	pb = psbuf_makeout();
     99        1.1   pooka 	psbuf_put_1(pb, SSH_FXP_INIT);
    100        1.1   pooka 	psbuf_put_4(pb, SFTP_PROTOVERSION);
    101       1.19   pooka 	DO_IO(psbuf_write, pu, pb, fd, &done, rv);
    102        1.1   pooka 
    103        1.8   pooka 	puffs_framebuf_recycle(pb);
    104       1.19   pooka 	DO_IO(psbuf_read, pu, pb, fd, &done, rv);
    105        1.8   pooka 	if (psbuf_get_type(pb) != SSH_FXP_VERSION)
    106       1.17   pooka 		reterr((stderr, "invalid server response: %d",
    107       1.17   pooka 		    psbuf_get_type(pb)), EPROTO);
    108        1.8   pooka 	pctx->protover = psbuf_get_reqid(pb);
    109       1.18   pooka 
    110       1.18   pooka 	/*
    111       1.18   pooka 	 * Check out which extensions are available.  Currently
    112       1.18   pooka 	 * we are only interested in the openssh statvfs extension.
    113       1.18   pooka 	 */
    114       1.18   pooka 	for (;;) {
    115       1.18   pooka 		if (psbuf_get_str(pb, &ext, NULL) != 0)
    116       1.18   pooka 			break;
    117       1.18   pooka 		if (psbuf_get_str(pb, &val, NULL) != 0)
    118       1.18   pooka 			break;
    119       1.19   pooka 
    120       1.18   pooka 		for (extu = exttable; extu->ext; extu++)
    121       1.18   pooka 			if (strcmp(ext, extu->ext) == 0
    122       1.18   pooka 			    && strcmp(val, extu->val) == 0)
    123       1.18   pooka 				pctx->extensions |= extu->extflag;
    124       1.18   pooka 	}
    125        1.1   pooka 
    126        1.1   pooka 	/* scope out our rootpath */
    127        1.8   pooka 	psbuf_recycleout(pb);
    128        1.1   pooka 	psbuf_put_1(pb, SSH_FXP_REALPATH);
    129        1.1   pooka 	psbuf_put_4(pb, NEXTREQ(pctx));
    130        1.1   pooka 	psbuf_put_str(pb, pctx->mountpath);
    131       1.19   pooka 	DO_IO(psbuf_write, pu, pb, fd, &done, rv);
    132        1.8   pooka 
    133        1.8   pooka 	puffs_framebuf_recycle(pb);
    134       1.19   pooka 	DO_IO(psbuf_read, pu, pb, fd, &done, rv);
    135        1.8   pooka 	if (psbuf_get_type(pb) != SSH_FXP_NAME)
    136       1.17   pooka 		reterr((stderr, "invalid server realpath response for \"%s\"",
    137       1.17   pooka 		    pctx->mountpath), EPROTO);
    138        1.8   pooka 	if (psbuf_get_4(pb, &count) == -1)
    139       1.17   pooka 		reterr((stderr, "invalid realpath response: count"), EPROTO);
    140        1.8   pooka 	if (psbuf_get_str(pb, &rootpath, NULL) == -1)
    141       1.17   pooka 		reterr((stderr, "invalid realpath response: rootpath"), EPROTO);
    142        1.1   pooka 
    143        1.1   pooka 	/* stat the rootdir so that we know it's a dir */
    144        1.8   pooka 	psbuf_recycleout(pb);
    145        1.1   pooka 	psbuf_req_str(pb, SSH_FXP_LSTAT, NEXTREQ(pctx), rootpath);
    146       1.19   pooka 	DO_IO(psbuf_write, pu, pb, fd, &done, rv);
    147        1.8   pooka 
    148        1.8   pooka 	puffs_framebuf_recycle(pb);
    149       1.19   pooka 	DO_IO(psbuf_read, pu, pb, fd, &done, rv);
    150        1.1   pooka 
    151        1.1   pooka 	rv = psbuf_expect_attrs(pb, &va);
    152        1.1   pooka 	if (rv)
    153       1.17   pooka 		reterr((stderr, "couldn't stat rootpath"), rv);
    154        1.8   pooka 	puffs_framebuf_destroy(pb);
    155        1.1   pooka 
    156        1.1   pooka 	if (puffs_mode2vt(va.va_mode) != VDIR)
    157       1.17   pooka 		reterr((stderr, "remote path (%s) not a directory", rootpath),
    158       1.17   pooka 		    ENOTDIR);
    159        1.1   pooka 
    160       1.17   pooka 	pn_root = puffs_getroot(pu);
    161       1.17   pooka 	rva = &pn_root->pn_va;
    162       1.17   pooka 	puffs_setvattr(rva, &va);
    163        1.3   pooka 
    164        1.3   pooka 	po_root = puffs_getrootpathobj(pu);
    165        1.3   pooka 	if (po_root == NULL)
    166        1.3   pooka 		err(1, "getrootpathobj");
    167        1.3   pooka 	po_root->po_path = rootpath;
    168        1.3   pooka 	po_root->po_len = strlen(rootpath);
    169        1.1   pooka 
    170        1.1   pooka 	return 0;
    171        1.1   pooka }
    172        1.1   pooka 
    173        1.1   pooka int
    174  1.24.42.1  martin psshfs_fs_statvfs(struct puffs_usermount *pu, struct puffs_statvfs *sbp)
    175       1.18   pooka {
    176       1.18   pooka 	PSSHFSAUTOVAR(pu);
    177       1.18   pooka 	uint64_t tmpval;
    178       1.18   pooka 	uint8_t type;
    179       1.18   pooka 
    180       1.18   pooka 	memset(sbp, 0, sizeof(*sbp));
    181       1.18   pooka 	sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = 512;
    182       1.18   pooka 
    183       1.18   pooka 	if ((pctx->extensions & SFTP_EXT_STATVFS) == 0)
    184       1.18   pooka 		goto out;
    185       1.18   pooka 
    186       1.18   pooka 	psbuf_req_str(pb, SSH_FXP_EXTENDED, reqid, "statvfs (at) openssh.com");
    187       1.18   pooka 	psbuf_put_str(pb, pctx->mountpath);
    188       1.19   pooka 	GETRESPONSE(pb, pctx->sshfd);
    189       1.18   pooka 
    190       1.18   pooka 	type = psbuf_get_type(pb);
    191       1.18   pooka 	if (type != SSH_FXP_EXTENDED_REPLY) {
    192       1.18   pooka 		/* use the default */
    193       1.18   pooka 		goto out;
    194       1.18   pooka 	}
    195       1.18   pooka 
    196       1.18   pooka 	psbuf_get_8(pb, &tmpval);
    197       1.18   pooka 	sbp->f_bsize = tmpval;
    198       1.18   pooka 	psbuf_get_8(pb, &tmpval);
    199       1.18   pooka 	sbp->f_frsize = tmpval;
    200       1.18   pooka 	psbuf_get_8(pb, &sbp->f_blocks);
    201       1.18   pooka 	psbuf_get_8(pb, &sbp->f_bfree);
    202       1.18   pooka 	psbuf_get_8(pb, &sbp->f_bavail);
    203       1.18   pooka 	psbuf_get_8(pb, &sbp->f_files);
    204       1.18   pooka 	psbuf_get_8(pb, &sbp->f_ffree);
    205       1.18   pooka 	psbuf_get_8(pb, &sbp->f_favail);
    206       1.18   pooka 
    207       1.18   pooka 	psbuf_get_8(pb, &tmpval); /* fsid */
    208       1.18   pooka 	psbuf_get_8(pb, &tmpval); /* flag */
    209       1.18   pooka 	psbuf_get_8(pb, &tmpval);
    210       1.18   pooka 	sbp->f_namemax = tmpval;
    211       1.18   pooka 
    212       1.21   pooka 	sbp->f_bresvd = sbp->f_bfree - sbp->f_bavail;
    213       1.21   pooka 	sbp->f_fresvd = sbp->f_ffree - sbp->f_favail;
    214       1.21   pooka 
    215       1.18   pooka  out:
    216       1.18   pooka 	PSSHFSRETURN(rv);
    217       1.18   pooka }
    218       1.18   pooka 
    219       1.18   pooka int
    220       1.15   pooka psshfs_fs_unmount(struct puffs_usermount *pu, int flags)
    221        1.1   pooka {
    222        1.4   pooka 	struct psshfs_ctx *pctx = puffs_getspecific(pu);
    223        1.1   pooka 
    224        1.1   pooka 	kill(pctx->sshpid, SIGTERM);
    225        1.1   pooka 	close(pctx->sshfd);
    226       1.19   pooka 	if (pctx->numconnections == 2) {
    227       1.19   pooka 		kill(pctx->sshpid_data, SIGTERM);
    228       1.19   pooka 		close(pctx->sshfd_data);
    229       1.19   pooka 	}
    230       1.19   pooka 
    231        1.1   pooka 	return 0;
    232        1.1   pooka }
    233        1.5   pooka 
    234        1.5   pooka int
    235       1.16   pooka psshfs_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie,
    236        1.5   pooka 	void *fid, size_t *fidsize)
    237        1.5   pooka {
    238        1.5   pooka 	struct psshfs_ctx *pctx = puffs_getspecific(pu);
    239        1.5   pooka 	struct puffs_node *pn = cookie;
    240        1.5   pooka 	struct psshfs_node *psn = pn->pn_data;
    241        1.5   pooka 	struct psshfs_fid *pf = fid;
    242        1.5   pooka 
    243        1.5   pooka 	pf->mounttime = pctx->mounttime;
    244        1.5   pooka 	pf->node = pn;
    245        1.5   pooka 
    246       1.10   pooka 	psn->stat |= PSN_HASFH;
    247        1.5   pooka 
    248        1.5   pooka 	return 0;
    249        1.5   pooka }
    250        1.5   pooka 
    251        1.5   pooka int
    252       1.15   pooka psshfs_fs_fhtonode(struct puffs_usermount *pu, void *fid, size_t fidsize,
    253       1.13   pooka 	struct puffs_newinfo *pni)
    254        1.5   pooka {
    255        1.5   pooka 	struct psshfs_ctx *pctx = puffs_getspecific(pu);
    256        1.5   pooka 	struct psshfs_fid *pf = fid;
    257        1.5   pooka 	struct puffs_node *pn = pf->node;
    258        1.5   pooka 	struct psshfs_node *psn;
    259        1.5   pooka 	int rv;
    260        1.5   pooka 
    261        1.5   pooka 	if (pf->mounttime != pctx->mounttime)
    262        1.5   pooka 		return EINVAL;
    263        1.5   pooka 	if (pn == 0)
    264        1.5   pooka 		return EINVAL;
    265        1.5   pooka 	psn = pn->pn_data;
    266       1.10   pooka 	if ((psn->stat & PSN_HASFH) == 0)
    267        1.5   pooka 		return EINVAL;
    268        1.5   pooka 
    269        1.5   pooka 	/* update node attributes */
    270       1.22   pooka 	rv = getnodeattr(pu, pn, NULL);
    271        1.6   pooka 	if (rv)
    272        1.5   pooka 		return EINVAL;
    273        1.5   pooka 
    274       1.13   pooka 	puffs_newinfo_setcookie(pni, pn);
    275       1.13   pooka 	puffs_newinfo_setvtype(pni, pn->pn_va.va_type);
    276       1.13   pooka 	puffs_newinfo_setsize(pni, pn->pn_va.va_size);
    277        1.5   pooka 
    278        1.5   pooka 	return 0;
    279        1.5   pooka }
    280