Wed May 20 13:56:36 2009 UTC ()
Introduce -c [12], which can be used to open 1 or 2 ssh connections
to the server.  If "2" is specified, a separate connection is used
for data and directory operations.  Using two connections can
significantly increase directory operation performance on a saturated
link, at least up to 30x faster.


(pooka)
diff -r1.18 -r1.19 src/usr.sbin/puffs/mount_psshfs/fs.c
diff -r1.19 -r1.20 src/usr.sbin/puffs/mount_psshfs/mount_psshfs.8
diff -r1.56 -r1.57 src/usr.sbin/puffs/mount_psshfs/node.c
diff -r1.50 -r1.51 src/usr.sbin/puffs/mount_psshfs/psshfs.c
diff -r1.35 -r1.36 src/usr.sbin/puffs/mount_psshfs/psshfs.h
diff -r1.45 -r1.46 src/usr.sbin/puffs/mount_psshfs/subr.c

cvs diff -r1.18 -r1.19 src/usr.sbin/puffs/mount_psshfs/fs.c (expand / switch to unified diff)

--- src/usr.sbin/puffs/mount_psshfs/fs.c 2009/02/23 18:43:46 1.18
+++ src/usr.sbin/puffs/mount_psshfs/fs.c 2009/05/20 13:56:36 1.19
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: fs.c,v 1.18 2009/02/23 18:43:46 pooka Exp $ */ 1/* $NetBSD: fs.c,v 1.19 2009/05/20 13:56:36 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE. 25 * SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29#ifndef lint 29#ifndef lint
30__RCSID("$NetBSD: fs.c,v 1.18 2009/02/23 18:43:46 pooka Exp $"); 30__RCSID("$NetBSD: fs.c,v 1.19 2009/05/20 13:56:36 pooka Exp $");
31#endif /* !lint */ 31#endif /* !lint */
32 32
33#include <err.h> 33#include <err.h>
34#include <errno.h> 34#include <errno.h>
35#include <puffs.h> 35#include <puffs.h>
36#include <signal.h> 36#include <signal.h>
37#include <stdio.h> 37#include <stdio.h>
38#include <stdlib.h> 38#include <stdlib.h>
39#include <unistd.h> 39#include <unistd.h>
40 40
41#include "psshfs.h" 41#include "psshfs.h"
42#include "sftp_proto.h" 42#include "sftp_proto.h"
43 43
@@ -74,91 +74,91 @@ static const struct extunit { @@ -74,91 +74,91 @@ static const struct extunit {
74 "2", 74 "2",
75 SFTP_EXT_STATVFS, 75 SFTP_EXT_STATVFS,
76},{ 76},{
77 "fstatvfs@openssh.com", 77 "fstatvfs@openssh.com",
78 "2", 78 "2",
79 SFTP_EXT_FSTATVFS, 79 SFTP_EXT_FSTATVFS,
80},{ 80},{
81 NULL, 81 NULL,
82 NULL, 82 NULL,
83 0 83 0
84}}; 84}};
85  85
86int 86int
87psshfs_handshake(struct puffs_usermount *pu) 87psshfs_handshake(struct puffs_usermount *pu, int fd)
88{ 88{
89 struct psshfs_ctx *pctx = puffs_getspecific(pu); 89 struct psshfs_ctx *pctx = puffs_getspecific(pu);
90 struct puffs_framebuf *pb; 90 struct puffs_framebuf *pb;
91 struct puffs_pathobj *po_root; 91 struct puffs_pathobj *po_root;
92 struct puffs_node *pn_root; 92 struct puffs_node *pn_root;
93 struct vattr va, *rva; 93 struct vattr va, *rva;
94 const struct extunit *extu; 94 const struct extunit *extu;
95 char *rootpath; 95 char *rootpath;
96 char *ext, *val; 96 char *ext, *val;
97 uint32_t count; 97 uint32_t count;
98 int rv, done; 98 int rv, done;
99 99
100 pb = psbuf_makeout(); 100 pb = psbuf_makeout();
101 psbuf_put_1(pb, SSH_FXP_INIT); 101 psbuf_put_1(pb, SSH_FXP_INIT);
102 psbuf_put_4(pb, SFTP_PROTOVERSION); 102 psbuf_put_4(pb, SFTP_PROTOVERSION);
103 DO_IO(psbuf_write, pu, pb, pctx->sshfd, &done, rv); 103 DO_IO(psbuf_write, pu, pb, fd, &done, rv);
104 104
105 puffs_framebuf_recycle(pb); 105 puffs_framebuf_recycle(pb);
106 DO_IO(psbuf_read, pu, pb, pctx->sshfd, &done, rv); 106 DO_IO(psbuf_read, pu, pb, fd, &done, rv);
107 if (psbuf_get_type(pb) != SSH_FXP_VERSION) 107 if (psbuf_get_type(pb) != SSH_FXP_VERSION)
108 reterr((stderr, "invalid server response: %d", 108 reterr((stderr, "invalid server response: %d",
109 psbuf_get_type(pb)), EPROTO); 109 psbuf_get_type(pb)), EPROTO);
110 pctx->protover = psbuf_get_reqid(pb); 110 pctx->protover = psbuf_get_reqid(pb);
111 111
112 /* 112 /*
113 * Check out which extensions are available. Currently 113 * Check out which extensions are available. Currently
114 * we are only interested in the openssh statvfs extension. 114 * we are only interested in the openssh statvfs extension.
115 */ 115 */
116 for (;;) { 116 for (;;) {
117 if (psbuf_get_str(pb, &ext, NULL) != 0) 117 if (psbuf_get_str(pb, &ext, NULL) != 0)
118 break; 118 break;
119 if (psbuf_get_str(pb, &val, NULL) != 0) 119 if (psbuf_get_str(pb, &val, NULL) != 0)
120 break; 120 break;
121  121
122 for (extu = exttable; extu->ext; extu++) 122 for (extu = exttable; extu->ext; extu++)
123 if (strcmp(ext, extu->ext) == 0 123 if (strcmp(ext, extu->ext) == 0
124 && strcmp(val, extu->val) == 0) 124 && strcmp(val, extu->val) == 0)
125 pctx->extensions |= extu->extflag; 125 pctx->extensions |= extu->extflag;
126 } 126 }
127 127
128 /* scope out our rootpath */ 128 /* scope out our rootpath */
129 psbuf_recycleout(pb); 129 psbuf_recycleout(pb);
130 psbuf_put_1(pb, SSH_FXP_REALPATH); 130 psbuf_put_1(pb, SSH_FXP_REALPATH);
131 psbuf_put_4(pb, NEXTREQ(pctx)); 131 psbuf_put_4(pb, NEXTREQ(pctx));
132 psbuf_put_str(pb, pctx->mountpath); 132 psbuf_put_str(pb, pctx->mountpath);
133 DO_IO(psbuf_write, pu, pb, pctx->sshfd, &done, rv); 133 DO_IO(psbuf_write, pu, pb, fd, &done, rv);
134 134
135 puffs_framebuf_recycle(pb); 135 puffs_framebuf_recycle(pb);
136 DO_IO(psbuf_read, pu, pb, pctx->sshfd, &done, rv); 136 DO_IO(psbuf_read, pu, pb, fd, &done, rv);
137 if (psbuf_get_type(pb) != SSH_FXP_NAME) 137 if (psbuf_get_type(pb) != SSH_FXP_NAME)
138 reterr((stderr, "invalid server realpath response for \"%s\"", 138 reterr((stderr, "invalid server realpath response for \"%s\"",
139 pctx->mountpath), EPROTO); 139 pctx->mountpath), EPROTO);
140 if (psbuf_get_4(pb, &count) == -1) 140 if (psbuf_get_4(pb, &count) == -1)
141 reterr((stderr, "invalid realpath response: count"), EPROTO); 141 reterr((stderr, "invalid realpath response: count"), EPROTO);
142 if (psbuf_get_str(pb, &rootpath, NULL) == -1) 142 if (psbuf_get_str(pb, &rootpath, NULL) == -1)
143 reterr((stderr, "invalid realpath response: rootpath"), EPROTO); 143 reterr((stderr, "invalid realpath response: rootpath"), EPROTO);
144 144
145 /* stat the rootdir so that we know it's a dir */ 145 /* stat the rootdir so that we know it's a dir */
146 psbuf_recycleout(pb); 146 psbuf_recycleout(pb);
147 psbuf_req_str(pb, SSH_FXP_LSTAT, NEXTREQ(pctx), rootpath); 147 psbuf_req_str(pb, SSH_FXP_LSTAT, NEXTREQ(pctx), rootpath);
148 DO_IO(psbuf_write, pu, pb, pctx->sshfd, &done, rv); 148 DO_IO(psbuf_write, pu, pb, fd, &done, rv);
149 149
150 puffs_framebuf_recycle(pb); 150 puffs_framebuf_recycle(pb);
151 DO_IO(psbuf_read, pu, pb, pctx->sshfd, &done, rv); 151 DO_IO(psbuf_read, pu, pb, fd, &done, rv);
152 152
153 rv = psbuf_expect_attrs(pb, &va); 153 rv = psbuf_expect_attrs(pb, &va);
154 if (rv) 154 if (rv)
155 reterr((stderr, "couldn't stat rootpath"), rv); 155 reterr((stderr, "couldn't stat rootpath"), rv);
156 puffs_framebuf_destroy(pb); 156 puffs_framebuf_destroy(pb);
157 157
158 if (puffs_mode2vt(va.va_mode) != VDIR) 158 if (puffs_mode2vt(va.va_mode) != VDIR)
159 reterr((stderr, "remote path (%s) not a directory", rootpath), 159 reterr((stderr, "remote path (%s) not a directory", rootpath),
160 ENOTDIR); 160 ENOTDIR);
161 161
162 pn_root = puffs_getroot(pu); 162 pn_root = puffs_getroot(pu);
163 rva = &pn_root->pn_va; 163 rva = &pn_root->pn_va;
164 puffs_setvattr(rva, &va); 164 puffs_setvattr(rva, &va);
@@ -177,27 +177,27 @@ psshfs_fs_statvfs(struct puffs_usermount @@ -177,27 +177,27 @@ psshfs_fs_statvfs(struct puffs_usermount
177{ 177{
178 PSSHFSAUTOVAR(pu); 178 PSSHFSAUTOVAR(pu);
179 uint64_t tmpval; 179 uint64_t tmpval;
180 uint8_t type; 180 uint8_t type;
181 181
182 memset(sbp, 0, sizeof(*sbp)); 182 memset(sbp, 0, sizeof(*sbp));
183 sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = 512; 183 sbp->f_bsize = sbp->f_frsize = sbp->f_iosize = 512;
184 184
185 if ((pctx->extensions & SFTP_EXT_STATVFS) == 0) 185 if ((pctx->extensions & SFTP_EXT_STATVFS) == 0)
186 goto out; 186 goto out;
187 187
188 psbuf_req_str(pb, SSH_FXP_EXTENDED, reqid, "statvfs@openssh.com"); 188 psbuf_req_str(pb, SSH_FXP_EXTENDED, reqid, "statvfs@openssh.com");
189 psbuf_put_str(pb, pctx->mountpath); 189 psbuf_put_str(pb, pctx->mountpath);
190 GETRESPONSE(pb); 190 GETRESPONSE(pb, pctx->sshfd);
191 191
192 type = psbuf_get_type(pb); 192 type = psbuf_get_type(pb);
193 if (type != SSH_FXP_EXTENDED_REPLY) { 193 if (type != SSH_FXP_EXTENDED_REPLY) {
194 /* use the default */ 194 /* use the default */
195 goto out; 195 goto out;
196 } 196 }
197 197
198 psbuf_get_8(pb, &tmpval); 198 psbuf_get_8(pb, &tmpval);
199 sbp->f_bsize = tmpval; 199 sbp->f_bsize = tmpval;
200 psbuf_get_8(pb, &tmpval); 200 psbuf_get_8(pb, &tmpval);
201 sbp->f_frsize = tmpval; 201 sbp->f_frsize = tmpval;
202 psbuf_get_8(pb, &sbp->f_blocks); 202 psbuf_get_8(pb, &sbp->f_blocks);
203 psbuf_get_8(pb, &sbp->f_bfree); 203 psbuf_get_8(pb, &sbp->f_bfree);
@@ -212,26 +212,31 @@ psshfs_fs_statvfs(struct puffs_usermount @@ -212,26 +212,31 @@ psshfs_fs_statvfs(struct puffs_usermount
212 sbp->f_namemax = tmpval; 212 sbp->f_namemax = tmpval;
213 213
214 out: 214 out:
215 PSSHFSRETURN(rv); 215 PSSHFSRETURN(rv);
216} 216}
217 217
218int 218int
219psshfs_fs_unmount(struct puffs_usermount *pu, int flags) 219psshfs_fs_unmount(struct puffs_usermount *pu, int flags)
220{ 220{
221 struct psshfs_ctx *pctx = puffs_getspecific(pu); 221 struct psshfs_ctx *pctx = puffs_getspecific(pu);
222 222
223 kill(pctx->sshpid, SIGTERM); 223 kill(pctx->sshpid, SIGTERM);
224 close(pctx->sshfd); 224 close(pctx->sshfd);
 225 if (pctx->numconnections == 2) {
 226 kill(pctx->sshpid_data, SIGTERM);
 227 close(pctx->sshfd_data);
 228 }
 229
225 return 0; 230 return 0;
226} 231}
227 232
228int 233int
229psshfs_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie, 234psshfs_fs_nodetofh(struct puffs_usermount *pu, puffs_cookie_t cookie,
230 void *fid, size_t *fidsize) 235 void *fid, size_t *fidsize)
231{ 236{
232 struct psshfs_ctx *pctx = puffs_getspecific(pu); 237 struct psshfs_ctx *pctx = puffs_getspecific(pu);
233 struct puffs_node *pn = cookie; 238 struct puffs_node *pn = cookie;
234 struct psshfs_node *psn = pn->pn_data; 239 struct psshfs_node *psn = pn->pn_data;
235 struct psshfs_fid *pf = fid; 240 struct psshfs_fid *pf = fid;
236 241
237 pf->mounttime = pctx->mounttime; 242 pf->mounttime = pctx->mounttime;

cvs diff -r1.19 -r1.20 src/usr.sbin/puffs/mount_psshfs/mount_psshfs.8 (expand / switch to unified diff)

--- src/usr.sbin/puffs/mount_psshfs/mount_psshfs.8 2009/02/26 07:14:36 1.19
+++ src/usr.sbin/puffs/mount_psshfs/mount_psshfs.8 2009/05/20 13:56:36 1.20
@@ -1,39 +1,39 @@ @@ -1,39 +1,39 @@
1.\" $NetBSD: mount_psshfs.8,v 1.19 2009/02/26 07:14:36 wiz Exp $ 1.\" $NetBSD: mount_psshfs.8,v 1.20 2009/05/20 13:56:36 pooka Exp $
2.\" 2.\"
3.\" Copyright (c) 2007 Antti Kantee. All rights reserved. 3.\" Copyright (c) 2007 Antti Kantee. All rights reserved.
4.\" 4.\"
5.\" Redistribution and use in source and binary forms, with or without 5.\" Redistribution and use in source and binary forms, with or without
6.\" modification, are permitted provided that the following conditions 6.\" modification, are permitted provided that the following conditions
7.\" are met: 7.\" are met:
8.\" 1. Redistributions of source code must retain the above copyright 8.\" 1. Redistributions of source code must retain the above copyright
9.\" notice, this list of conditions and the following disclaimer. 9.\" notice, this list of conditions and the following disclaimer.
10.\" 2. Redistributions in binary form must reproduce the above copyright 10.\" 2. Redistributions in binary form must reproduce the above copyright
11.\" notice, this list of conditions and the following disclaimer in the 11.\" notice, this list of conditions and the following disclaimer in the
12.\" documentation and/or other materials provided with the distribution. 12.\" documentation and/or other materials provided with the distribution.
13.\" 13.\"
14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 14.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 15.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 16.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 17.\" ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 18.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 19.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 20.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 21.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 22.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 23.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24.\" SUCH DAMAGE. 24.\" SUCH DAMAGE.
25.\" 25.\"
26.Dd February 25, 2009 26.Dd May 20, 2009
27.Dt MOUNT_PSSHFS 8 27.Dt MOUNT_PSSHFS 8
28.Os 28.Os
29.Sh NAME 29.Sh NAME
30.Nm mount_psshfs 30.Nm mount_psshfs
31.Nd sshfs implementation for puffs 31.Nd sshfs implementation for puffs
32.Sh SYNOPSIS 32.Sh SYNOPSIS
33.Nm 33.Nm
34.Op Ar options 34.Op Ar options
35.Ar user@host[:path] 35.Ar user@host[:path]
36.Ar mount_point 36.Ar mount_point
37.Sh DESCRIPTION 37.Sh DESCRIPTION
38The 38The
39.Nm 39.Nm
@@ -46,26 +46,39 @@ This functionality is commonly known as @@ -46,26 +46,39 @@ This functionality is commonly known as
46The mandatory parameters are the target host name and local mount 46The mandatory parameters are the target host name and local mount
47point. 47point.
48The target host parameter can optionally contain a username whose 48The target host parameter can optionally contain a username whose
49credentials will be used by the remote sshd, and a relative or 49credentials will be used by the remote sshd, and a relative or
50absolute path for the remote mount point's root. 50absolute path for the remote mount point's root.
51If no user is given, the credentials of the user issuing the mount 51If no user is given, the credentials of the user issuing the mount
52command are used. 52command are used.
53If no path is given, the user's home directory on the remote machine 53If no path is given, the user's home directory on the remote machine
54will be used. 54will be used.
55.Pp 55.Pp
56The following command line options are available: 56The following command line options are available:
57.Pp 57.Pp
58.Bl -tag -width xxx 58.Bl -tag -width xxx
 59.It Fl c Ar nconnect
 60Opens
 61.Ar nconnect
 62connections to the server.
 63Currently, the value has to be 1 or 2.
 64If 2 is specified, a second connection is opened for the reading
 65and writing of data, while directory operations are performed on
 66their own connection.
 67This can greatly increase directory operation performance (ls,
 68mkdir, etc.) if
 69.Nm
 70completely saturates the available bandwidth by doing bulk data copying.
 71The default is 1.
59.It Fl e 72.It Fl e
60Makes the mounted file system NFS exportable. 73Makes the mounted file system NFS exportable.
61If this option is used, it is very important to understand that 74If this option is used, it is very important to understand that
62.Nm 75.Nm
63can not provide complete support for NFS due to the limitations in 76can not provide complete support for NFS due to the limitations in
64the backend. 77the backend.
65Files are valid only for the time that 78Files are valid only for the time that
66.Nm 79.Nm
67is running and in the event of e.g. a server crash, all client retries 80is running and in the event of e.g. a server crash, all client retries
68to access files will fail. 81to access files will fail.
69.It Fl F Ar configfile 82.It Fl F Ar configfile
70Pass a configuration file to 83Pass a configuration file to
71.Xr ssh 1 . 84.Xr ssh 1 .

cvs diff -r1.56 -r1.57 src/usr.sbin/puffs/mount_psshfs/node.c (expand / switch to unified diff)

--- src/usr.sbin/puffs/mount_psshfs/node.c 2009/03/29 16:06:53 1.56
+++ src/usr.sbin/puffs/mount_psshfs/node.c 2009/05/20 13:56:36 1.57
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: node.c,v 1.56 2009/03/29 16:06:53 pooka Exp $ */ 1/* $NetBSD: node.c,v 1.57 2009/05/20 13:56:36 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE. 25 * SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29#ifndef lint 29#ifndef lint
30__RCSID("$NetBSD: node.c,v 1.56 2009/03/29 16:06:53 pooka Exp $"); 30__RCSID("$NetBSD: node.c,v 1.57 2009/05/20 13:56:36 pooka Exp $");
31#endif /* !lint */ 31#endif /* !lint */
32 32
33#include <assert.h> 33#include <assert.h>
34#include <errno.h> 34#include <errno.h>
35#include <stdio.h> 35#include <stdio.h>
36#include <stdlib.h> 36#include <stdlib.h>
37 37
38#include "psshfs.h" 38#include "psshfs.h"
39#include "sftp_proto.h" 39#include "sftp_proto.h"
40 40
41int 41int
42psshfs_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc, 42psshfs_node_lookup(struct puffs_usermount *pu, puffs_cookie_t opc,
43 struct puffs_newinfo *pni, const struct puffs_cn *pcn) 43 struct puffs_newinfo *pni, const struct puffs_cn *pcn)
@@ -138,79 +138,79 @@ psshfs_node_setattr(struct puffs_usermou @@ -138,79 +138,79 @@ psshfs_node_setattr(struct puffs_usermou
138 kludgeva.va_mtime.tv_sec = pn->pn_va.va_mtime.tv_sec; 138 kludgeva.va_mtime.tv_sec = pn->pn_va.va_mtime.tv_sec;
139 else 139 else
140 kludgeva.va_mtime.tv_sec = va->va_atime.tv_sec; 140 kludgeva.va_mtime.tv_sec = va->va_atime.tv_sec;
141 } 141 }
142 if (va->va_mtime.tv_sec != PUFFS_VNOVAL 142 if (va->va_mtime.tv_sec != PUFFS_VNOVAL
143 && va->va_atime.tv_sec == PUFFS_VNOVAL) { 143 && va->va_atime.tv_sec == PUFFS_VNOVAL) {
144 if (pn->pn_va.va_atime.tv_sec != PUFFS_VNOVAL) 144 if (pn->pn_va.va_atime.tv_sec != PUFFS_VNOVAL)
145 kludgeva.va_atime.tv_sec = pn->pn_va.va_atime.tv_sec; 145 kludgeva.va_atime.tv_sec = pn->pn_va.va_atime.tv_sec;
146 else 146 else
147 kludgeva.va_atime.tv_sec = va->va_mtime.tv_sec; 147 kludgeva.va_atime.tv_sec = va->va_mtime.tv_sec;
148 } 148 }
149  149
150 psbuf_put_vattr(pb, &kludgeva); 150 psbuf_put_vattr(pb, &kludgeva);
151 GETRESPONSE(pb); 151 GETRESPONSE(pb, pctx->sshfd);
152 152
153 rv = psbuf_expect_status(pb); 153 rv = psbuf_expect_status(pb);
154 if (rv == 0) 154 if (rv == 0)
155 puffs_setvattr(&pn->pn_va, &kludgeva); 155 puffs_setvattr(&pn->pn_va, &kludgeva);
156 156
157 out: 157 out:
158 PSSHFSRETURN(rv); 158 PSSHFSRETURN(rv);
159} 159}
160 160
161int 161int
162psshfs_node_create(struct puffs_usermount *pu, puffs_cookie_t opc, 162psshfs_node_create(struct puffs_usermount *pu, puffs_cookie_t opc,
163 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 163 struct puffs_newinfo *pni, const struct puffs_cn *pcn,
164 const struct vattr *va) 164 const struct vattr *va)
165{ 165{
166 PSSHFSAUTOVAR(pu); 166 PSSHFSAUTOVAR(pu);
167 struct puffs_node *pn = opc; 167 struct puffs_node *pn = opc;
168 struct puffs_node *pn_new; 168 struct puffs_node *pn_new;
169 char *fhand = NULL; 169 char *fhand = NULL;
170 uint32_t fhandlen; 170 uint32_t fhandlen;
171 171
172 /* Create node on server first */ 172 /* Create node on server first */
173 psbuf_req_str(pb, SSH_FXP_OPEN, reqid, PCNPATH(pcn)); 173 psbuf_req_str(pb, SSH_FXP_OPEN, reqid, PCNPATH(pcn));
174 psbuf_put_4(pb, SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC); 174 psbuf_put_4(pb, SSH_FXF_WRITE | SSH_FXF_CREAT | SSH_FXF_TRUNC);
175 psbuf_put_vattr(pb, va); 175 psbuf_put_vattr(pb, va);
176 GETRESPONSE(pb); 176 GETRESPONSE(pb, pctx->sshfd);
177 rv = psbuf_expect_handle(pb, &fhand, &fhandlen); 177 rv = psbuf_expect_handle(pb, &fhand, &fhandlen);
178 if (rv) 178 if (rv)
179 goto out; 179 goto out;
180 180
181 /* 181 /*
182 * Do *not* create the local node before getting a response 182 * Do *not* create the local node before getting a response
183 * from the server. Otherwise we might screw up consistency, 183 * from the server. Otherwise we might screw up consistency,
184 * namely that the node can be looked up before create has 184 * namely that the node can be looked up before create has
185 * returned (mind you, the kernel will unlock the directory 185 * returned (mind you, the kernel will unlock the directory
186 * before the create call from userspace returns). 186 * before the create call from userspace returns).
187 */ 187 */
188 pn_new = allocnode(pu, pn, pcn->pcn_name, va); 188 pn_new = allocnode(pu, pn, pcn->pcn_name, va);
189 if (!pn_new) { 189 if (!pn_new) {
190 struct puffs_framebuf *pb2 = psbuf_makeout(); 190 struct puffs_framebuf *pb2 = psbuf_makeout();
191 reqid = NEXTREQ(pctx); 191 reqid = NEXTREQ(pctx);
192 psbuf_req_str(pb2, SSH_FXP_REMOVE, reqid, PCNPATH(pcn)); 192 psbuf_req_str(pb2, SSH_FXP_REMOVE, reqid, PCNPATH(pcn));
193 JUSTSEND(pb2); 193 JUSTSEND(pb2, pctx->sshfd);
194 rv = ENOMEM; 194 rv = ENOMEM;
195 } 195 }
196 196
197 if (pn_new) 197 if (pn_new)
198 puffs_newinfo_setcookie(pni, pn_new); 198 puffs_newinfo_setcookie(pni, pn_new);
199 199
200 reqid = NEXTREQ(pctx); 200 reqid = NEXTREQ(pctx);
201 psbuf_recycleout(pb); 201 psbuf_recycleout(pb);
202 psbuf_req_data(pb, SSH_FXP_CLOSE, reqid, fhand, fhandlen); 202 psbuf_req_data(pb, SSH_FXP_CLOSE, reqid, fhand, fhandlen);
203 JUSTSEND(pb); 203 JUSTSEND(pb, pctx->sshfd);
204 free(fhand); 204 free(fhand);
205 return rv; 205 return rv;
206 206
207 out: 207 out:
208 free(fhand); 208 free(fhand);
209 PSSHFSRETURN(rv); 209 PSSHFSRETURN(rv);
210} 210}
211 211
212/* 212/*
213 * Open a file handle. This is used for read and write. We do not 213 * Open a file handle. This is used for read and write. We do not
214 * wait here for the success or failure of this operation. This is 214 * wait here for the success or failure of this operation. This is
215 * because otherwise opening and closing file handles would block 215 * because otherwise opening and closing file handles would block
216 * reading potentially cached information. Rather, we defer the wait 216 * reading potentially cached information. Rather, we defer the wait
@@ -238,45 +238,45 @@ psshfs_node_open(struct puffs_usermount  @@ -238,45 +238,45 @@ psshfs_node_open(struct puffs_usermount
238 return 0; 238 return 0;
239 239
240 puffs_setback(pcc, PUFFS_SETBACK_INACT_N1); 240 puffs_setback(pcc, PUFFS_SETBACK_INACT_N1);
241 puffs_vattr_null(&va); 241 puffs_vattr_null(&va);
242 didread = didwrite = 0; 242 didread = didwrite = 0;
243 if (mode & FREAD && psn->fhand_r == NULL && psn->lazyopen_r == NULL) { 243 if (mode & FREAD && psn->fhand_r == NULL && psn->lazyopen_r == NULL) {
244 pb = psbuf_makeout(); 244 pb = psbuf_makeout();
245 245
246 reqid = NEXTREQ(pctx); 246 reqid = NEXTREQ(pctx);
247 psbuf_req_str(pb, SSH_FXP_OPEN, reqid, PNPATH(pn)); 247 psbuf_req_str(pb, SSH_FXP_OPEN, reqid, PNPATH(pn));
248 psbuf_put_4(pb, SSH_FXF_READ); 248 psbuf_put_4(pb, SSH_FXF_READ);
249 psbuf_put_vattr(pb, &va); 249 psbuf_put_vattr(pb, &va);
250 250
251 if (puffs_framev_enqueue_cb(pu, pctx->sshfd, pb, 251 if (puffs_framev_enqueue_cb(pu, pctx->sshfd_data, pb,
252 lazyopen_rresp, psn, 0) == -1) { 252 lazyopen_rresp, psn, 0) == -1) {
253 rv = errno; 253 rv = errno;
254 puffs_framebuf_destroy(pb); 254 puffs_framebuf_destroy(pb);
255 goto out; 255 goto out;
256 } 256 }
257 257
258 psn->lazyopen_r = pb; 258 psn->lazyopen_r = pb;
259 didread = 1; 259 didread = 1;
260 } 260 }
261 if (mode & FWRITE && psn->fhand_w == NULL && psn->lazyopen_w == NULL) { 261 if (mode & FWRITE && psn->fhand_w == NULL && psn->lazyopen_w == NULL) {
262 pb2 = psbuf_makeout(); 262 pb2 = psbuf_makeout();
263 263
264 reqid = NEXTREQ(pctx); 264 reqid = NEXTREQ(pctx);
265 psbuf_req_str(pb2, SSH_FXP_OPEN, reqid, PNPATH(pn)); 265 psbuf_req_str(pb2, SSH_FXP_OPEN, reqid, PNPATH(pn));
266 psbuf_put_4(pb2, SSH_FXF_WRITE); 266 psbuf_put_4(pb2, SSH_FXF_WRITE);
267 psbuf_put_vattr(pb2, &va); 267 psbuf_put_vattr(pb2, &va);
268 268
269 if (puffs_framev_enqueue_cb(pu, pctx->sshfd, pb2, 269 if (puffs_framev_enqueue_cb(pu, pctx->sshfd_data, pb2,
270 lazyopen_wresp, psn, 0) == -1) { 270 lazyopen_wresp, psn, 0) == -1) {
271 rv = errno; 271 rv = errno;
272 puffs_framebuf_destroy(pb2); 272 puffs_framebuf_destroy(pb2);
273 goto out; 273 goto out;
274 } 274 }
275 275
276 psn->lazyopen_w = pb2; 276 psn->lazyopen_w = pb2;
277 didwrite = 1; 277 didwrite = 1;
278 } 278 }
279 psn->stat &= ~PSN_HANDLECLOSE; 279 psn->stat &= ~PSN_HANDLECLOSE;
280 280
281 out: 281 out:
282 /* wait? */ 282 /* wait? */
@@ -470,27 +470,27 @@ psshfs_node_read(struct puffs_usermount  @@ -470,27 +470,27 @@ psshfs_node_read(struct puffs_usermount
470 /* 470 /*
471 * Do this *after* accessing the file, the handle might not 471 * Do this *after* accessing the file, the handle might not
472 * exist after blocking. 472 * exist after blocking.
473 */ 473 */
474 if (max_reads && ++psn->readcount > max_reads) { 474 if (max_reads && ++psn->readcount > max_reads) {
475 struct psshfs_wait pw; 475 struct psshfs_wait pw;
476 476
477 pw.pw_cc = pcc; 477 pw.pw_cc = pcc;
478 pw.pw_type = PWTYPE_READ2; 478 pw.pw_type = PWTYPE_READ2;
479 TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries); 479 TAILQ_INSERT_TAIL(&psn->pw, &pw, pw_entries);
480 puffs_cc_yield(pcc); 480 puffs_cc_yield(pcc);
481 } 481 }
482 482
483 GETRESPONSE(pb); 483 GETRESPONSE(pb, pctx->sshfd_data);
484 484
485 rv = psbuf_do_data(pb, buf, &readlen); 485 rv = psbuf_do_data(pb, buf, &readlen);
486 if (rv == 0) 486 if (rv == 0)
487 *resid -= readlen; 487 *resid -= readlen;
488 488
489 out: 489 out:
490 if (max_reads && --psn->readcount >= max_reads) { 490 if (max_reads && --psn->readcount >= max_reads) {
491 TAILQ_FOREACH(pwp, &psn->pw, pw_entries) 491 TAILQ_FOREACH(pwp, &psn->pw, pw_entries)
492 if (pwp->pw_type == PWTYPE_READ2) 492 if (pwp->pw_type == PWTYPE_READ2)
493 break; 493 break;
494 assert(pwp != NULL); 494 assert(pwp != NULL);
495 puffs_cc_schedule(pwp->pw_cc); 495 puffs_cc_schedule(pwp->pw_cc);
496 TAILQ_REMOVE(&psn->pw, pwp, pw_entries); 496 TAILQ_REMOVE(&psn->pw, pwp, pw_entries);
@@ -564,27 +564,27 @@ psshfs_node_write(struct puffs_usermount @@ -564,27 +564,27 @@ psshfs_node_write(struct puffs_usermount
564 goto out; 564 goto out;
565 } 565 }
566 566
567 if (!psn->fhand_w) { 567 if (!psn->fhand_w) {
568 abort(); 568 abort();
569 rv = EINVAL; 569 rv = EINVAL;
570 goto out; 570 goto out;
571 } 571 }
572 572
573 writelen = *resid; 573 writelen = *resid;
574 psbuf_req_data(pb, SSH_FXP_WRITE, reqid, psn->fhand_w,psn->fhand_w_len); 574 psbuf_req_data(pb, SSH_FXP_WRITE, reqid, psn->fhand_w,psn->fhand_w_len);
575 psbuf_put_8(pb, offset); 575 psbuf_put_8(pb, offset);
576 psbuf_put_data(pb, buf, writelen); 576 psbuf_put_data(pb, buf, writelen);
577 GETRESPONSE(pb); 577 GETRESPONSE(pb, pctx->sshfd_data);
578 578
579 rv = psbuf_expect_status(pb); 579 rv = psbuf_expect_status(pb);
580 if (rv == 0) 580 if (rv == 0)
581 *resid = 0; 581 *resid = 0;
582 582
583 if (pn->pn_va.va_size < offset + writelen) 583 if (pn->pn_va.va_size < offset + writelen)
584 pn->pn_va.va_size = offset + writelen; 584 pn->pn_va.va_size = offset + writelen;
585 585
586 out: 586 out:
587 /* check if we need a lazyclose */ 587 /* check if we need a lazyclose */
588 if (psn->stat & PSN_HANDLECLOSE && psn->fhand_w) { 588 if (psn->stat & PSN_HANDLECLOSE && psn->fhand_w) {
589 TAILQ_FOREACH(pwp, &psn->pw, pw_entries) 589 TAILQ_FOREACH(pwp, &psn->pw, pw_entries)
590 if (pwp->pw_type == PWTYPE_WRITE) 590 if (pwp->pw_type == PWTYPE_WRITE)
@@ -616,27 +616,27 @@ psshfs_node_readlink(struct puffs_usermo @@ -616,27 +616,27 @@ psshfs_node_readlink(struct puffs_usermo
616 * from the server if we get many requests at once, but that's 616 * from the server if we get many requests at once, but that's
617 * quite harmless as this routine is reentrant. 617 * quite harmless as this routine is reentrant.
618 */ 618 */
619 if (psn->symlink && !REFRESHTIMEOUT(pctx, time(NULL) - psn->slread)) 619 if (psn->symlink && !REFRESHTIMEOUT(pctx, time(NULL) - psn->slread))
620 goto copy; 620 goto copy;
621 621
622 if (psn->symlink) { 622 if (psn->symlink) {
623 free(psn->symlink); 623 free(psn->symlink);
624 psn->symlink = NULL; 624 psn->symlink = NULL;
625 psn->slread = 0; 625 psn->slread = 0;
626 } 626 }
627 627
628 psbuf_req_str(pb, SSH_FXP_READLINK, reqid, PNPATH(pn)); 628 psbuf_req_str(pb, SSH_FXP_READLINK, reqid, PNPATH(pn));
629 GETRESPONSE(pb); 629 GETRESPONSE(pb, pctx->sshfd);
630 630
631 rv = psbuf_expect_name(pb, &count); 631 rv = psbuf_expect_name(pb, &count);
632 if (rv) 632 if (rv)
633 goto out; 633 goto out;
634 if (count != 1) { 634 if (count != 1) {
635 rv = EPROTO; 635 rv = EPROTO;
636 goto out; 636 goto out;
637 } 637 }
638 638
639 rv = psbuf_get_str(pb, &psn->symlink, NULL); 639 rv = psbuf_get_str(pb, &psn->symlink, NULL);
640 if (rv) 640 if (rv)
641 goto out; 641 goto out;
642 psn->slread = time(NULL); 642 psn->slread = time(NULL);
@@ -652,27 +652,27 @@ psshfs_node_readlink(struct puffs_usermo @@ -652,27 +652,27 @@ psshfs_node_readlink(struct puffs_usermo
652static int 652static int
653doremove(struct puffs_usermount *pu, struct puffs_node *pn_dir, 653doremove(struct puffs_usermount *pu, struct puffs_node *pn_dir,
654 struct puffs_node *pn, const char *name) 654 struct puffs_node *pn, const char *name)
655{ 655{
656 PSSHFSAUTOVAR(pu); 656 PSSHFSAUTOVAR(pu);
657 int op; 657 int op;
658 658
659 if (pn->pn_va.va_type == VDIR) 659 if (pn->pn_va.va_type == VDIR)
660 op = SSH_FXP_RMDIR; 660 op = SSH_FXP_RMDIR;
661 else 661 else
662 op = SSH_FXP_REMOVE; 662 op = SSH_FXP_REMOVE;
663 663
664 psbuf_req_str(pb, op, reqid, PNPATH(pn)); 664 psbuf_req_str(pb, op, reqid, PNPATH(pn));
665 GETRESPONSE(pb); 665 GETRESPONSE(pb, pctx->sshfd);
666 666
667 rv = psbuf_expect_status(pb); 667 rv = psbuf_expect_status(pb);
668 if (rv == 0) 668 if (rv == 0)
669 nukenode(pn, name, 0); 669 nukenode(pn, name, 0);
670 670
671 out: 671 out:
672 PSSHFSRETURN(rv); 672 PSSHFSRETURN(rv);
673} 673}
674 674
675int 675int
676psshfs_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc, 676psshfs_node_remove(struct puffs_usermount *pu, puffs_cookie_t opc,
677 puffs_cookie_t targ, const struct puffs_cn *pcn) 677 puffs_cookie_t targ, const struct puffs_cn *pcn)
678{ 678{
@@ -705,41 +705,41 @@ psshfs_node_rmdir(struct puffs_usermount @@ -705,41 +705,41 @@ psshfs_node_rmdir(struct puffs_usermount
705} 705}
706 706
707int 707int
708psshfs_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc, 708psshfs_node_mkdir(struct puffs_usermount *pu, puffs_cookie_t opc,
709 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 709 struct puffs_newinfo *pni, const struct puffs_cn *pcn,
710 const struct vattr *va) 710 const struct vattr *va)
711{ 711{
712 PSSHFSAUTOVAR(pu); 712 PSSHFSAUTOVAR(pu);
713 struct puffs_node *pn = opc; 713 struct puffs_node *pn = opc;
714 struct puffs_node *pn_new; 714 struct puffs_node *pn_new;
715 715
716 psbuf_req_str(pb, SSH_FXP_MKDIR, reqid, PCNPATH(pcn)); 716 psbuf_req_str(pb, SSH_FXP_MKDIR, reqid, PCNPATH(pcn));
717 psbuf_put_vattr(pb, va); 717 psbuf_put_vattr(pb, va);
718 GETRESPONSE(pb); 718 GETRESPONSE(pb, pctx->sshfd);
719 719
720 rv = psbuf_expect_status(pb); 720 rv = psbuf_expect_status(pb);
721 if (rv) 721 if (rv)
722 goto out; 722 goto out;
723 723
724 pn_new = allocnode(pu, pn, pcn->pcn_name, va); 724 pn_new = allocnode(pu, pn, pcn->pcn_name, va);
725 if (pn_new) { 725 if (pn_new) {
726 puffs_newinfo_setcookie(pni, pn_new); 726 puffs_newinfo_setcookie(pni, pn_new);
727 } else { 727 } else {
728 struct puffs_framebuf *pb2 = psbuf_makeout(); 728 struct puffs_framebuf *pb2 = psbuf_makeout();
729 reqid = NEXTREQ(pctx); 729 reqid = NEXTREQ(pctx);
730 psbuf_recycleout(pb2); 730 psbuf_recycleout(pb2);
731 psbuf_req_str(pb2, SSH_FXP_RMDIR, reqid, PCNPATH(pcn)); 731 psbuf_req_str(pb2, SSH_FXP_RMDIR, reqid, PCNPATH(pcn));
732 JUSTSEND(pb2); 732 JUSTSEND(pb2, pctx->sshfd);
733 rv = ENOMEM; 733 rv = ENOMEM;
734 } 734 }
735 735
736 out: 736 out:
737 PSSHFSRETURN(rv); 737 PSSHFSRETURN(rv);
738} 738}
739 739
740int 740int
741psshfs_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc, 741psshfs_node_symlink(struct puffs_usermount *pu, puffs_cookie_t opc,
742 struct puffs_newinfo *pni, const struct puffs_cn *pcn, 742 struct puffs_newinfo *pni, const struct puffs_cn *pcn,
743 const struct vattr *va, const char *link_target) 743 const struct vattr *va, const char *link_target)
744{ 744{
745 PSSHFSAUTOVAR(pu); 745 PSSHFSAUTOVAR(pu);
@@ -747,41 +747,41 @@ psshfs_node_symlink(struct puffs_usermou @@ -747,41 +747,41 @@ psshfs_node_symlink(struct puffs_usermou
747 struct puffs_node *pn_new; 747 struct puffs_node *pn_new;
748 748
749 if (pctx->protover < 3) { 749 if (pctx->protover < 3) {
750 rv = EOPNOTSUPP; 750 rv = EOPNOTSUPP;
751 goto out; 751 goto out;
752 } 752 }
753 753
754 /* 754 /*
755 * XXX: ietf says: source, target. openssh says: ietf who? 755 * XXX: ietf says: source, target. openssh says: ietf who?
756 * Let's go with openssh and build quirk tables later if we care 756 * Let's go with openssh and build quirk tables later if we care
757 */ 757 */
758 psbuf_req_str(pb, SSH_FXP_SYMLINK, reqid, link_target); 758 psbuf_req_str(pb, SSH_FXP_SYMLINK, reqid, link_target);
759 psbuf_put_str(pb, PCNPATH(pcn)); 759 psbuf_put_str(pb, PCNPATH(pcn));
760 GETRESPONSE(pb); 760 GETRESPONSE(pb, pctx->sshfd);
761 761
762 rv = psbuf_expect_status(pb); 762 rv = psbuf_expect_status(pb);
763 if (rv) 763 if (rv)
764 goto out; 764 goto out;
765 765
766 pn_new = allocnode(pu, pn, pcn->pcn_name, va); 766 pn_new = allocnode(pu, pn, pcn->pcn_name, va);
767 if (pn_new) { 767 if (pn_new) {
768 puffs_newinfo_setcookie(pni, pn_new); 768 puffs_newinfo_setcookie(pni, pn_new);
769 } else { 769 } else {
770 struct puffs_framebuf *pb2 = psbuf_makeout(); 770 struct puffs_framebuf *pb2 = psbuf_makeout();
771 reqid = NEXTREQ(pctx); 771 reqid = NEXTREQ(pctx);
772 psbuf_recycleout(pb2); 772 psbuf_recycleout(pb2);
773 psbuf_req_str(pb2, SSH_FXP_REMOVE, reqid, PCNPATH(pcn)); 773 psbuf_req_str(pb2, SSH_FXP_REMOVE, reqid, PCNPATH(pcn));
774 JUSTSEND(pb2); 774 JUSTSEND(pb2, pctx->sshfd);
775 rv = ENOMEM; 775 rv = ENOMEM;
776 } 776 }
777 777
778 out: 778 out:
779 PSSHFSRETURN(rv); 779 PSSHFSRETURN(rv);
780} 780}
781 781
782int 782int
783psshfs_node_rename(struct puffs_usermount *pu, puffs_cookie_t opc, 783psshfs_node_rename(struct puffs_usermount *pu, puffs_cookie_t opc,
784 puffs_cookie_t src, const struct puffs_cn *pcn_src, 784 puffs_cookie_t src, const struct puffs_cn *pcn_src,
785 puffs_cookie_t targ_dir, puffs_cookie_t targ, 785 puffs_cookie_t targ_dir, puffs_cookie_t targ,
786 const struct puffs_cn *pcn_targ) 786 const struct puffs_cn *pcn_targ)
787{ 787{
@@ -794,27 +794,27 @@ psshfs_node_rename(struct puffs_usermoun @@ -794,27 +794,27 @@ psshfs_node_rename(struct puffs_usermoun
794 if (pctx->protover < 2) { 794 if (pctx->protover < 2) {
795 rv = EOPNOTSUPP; 795 rv = EOPNOTSUPP;
796 goto out; 796 goto out;
797 } 797 }
798 798
799 if (pn_tf) { 799 if (pn_tf) {
800 rv = doremove(pu, targ_dir, pn_tf, pcn_targ->pcn_name); 800 rv = doremove(pu, targ_dir, pn_tf, pcn_targ->pcn_name);
801 if (rv) 801 if (rv)
802 goto out; 802 goto out;
803 } 803 }
804 804
805 psbuf_req_str(pb, SSH_FXP_RENAME, reqid, PCNPATH(pcn_src)); 805 psbuf_req_str(pb, SSH_FXP_RENAME, reqid, PCNPATH(pcn_src));
806 psbuf_put_str(pb, PCNPATH(pcn_targ)); 806 psbuf_put_str(pb, PCNPATH(pcn_targ));
807 GETRESPONSE(pb); 807 GETRESPONSE(pb, pctx->sshfd);
808 808
809 rv = psbuf_expect_status(pb); 809 rv = psbuf_expect_status(pb);
810 if (rv == 0) { 810 if (rv == 0) {
811 struct psshfs_dir *pd; 811 struct psshfs_dir *pd;
812 812
813 /* 813 /*
814 * XXX: interfaces didn't quite work with rename.. 814 * XXX: interfaces didn't quite work with rename..
815 * the song remains the same. go figure .. ;) 815 * the song remains the same. go figure .. ;)
816 */ 816 */
817 nukenode(pn_sf, pcn_src->pcn_name, 0); 817 nukenode(pn_sf, pcn_src->pcn_name, 0);
818 pd = direnter(pn_td, pcn_targ->pcn_name); 818 pd = direnter(pn_td, pcn_targ->pcn_name);
819 pd->entry = pn_sf; 819 pd->entry = pn_sf;
820 puffs_setvattr(&pd->va, &pn_sf->pn_va); 820 puffs_setvattr(&pd->va, &pn_sf->pn_va);

cvs diff -r1.50 -r1.51 src/usr.sbin/puffs/mount_psshfs/psshfs.c (expand / switch to unified diff)

--- src/usr.sbin/puffs/mount_psshfs/psshfs.c 2009/02/23 18:43:46 1.50
+++ src/usr.sbin/puffs/mount_psshfs/psshfs.c 2009/05/20 13:56:36 1.51
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: psshfs.c,v 1.50 2009/02/23 18:43:46 pooka Exp $ */ 1/* $NetBSD: psshfs.c,v 1.51 2009/05/20 13:56:36 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -31,73 +31,73 @@ @@ -31,73 +31,73 @@
31 * psshfs implements sshfs functionality on top of puffs making it 31 * psshfs implements sshfs functionality on top of puffs making it
32 * possible to mount a filesystme through the sftp service. 32 * possible to mount a filesystme through the sftp service.
33 * 33 *
34 * psshfs can execute multiple operations in "parallel" by using the 34 * psshfs can execute multiple operations in "parallel" by using the
35 * puffs_cc framework for continuations. 35 * puffs_cc framework for continuations.
36 * 36 *
37 * Concurrency control is handled currently by vnode locking (this 37 * Concurrency control is handled currently by vnode locking (this
38 * will change in the future). Context switch locations are easy to 38 * will change in the future). Context switch locations are easy to
39 * find by grepping for puffs_framebuf_enqueue_cc(). 39 * find by grepping for puffs_framebuf_enqueue_cc().
40 */ 40 */
41 41
42#include <sys/cdefs.h> 42#include <sys/cdefs.h>
43#ifndef lint 43#ifndef lint
44__RCSID("$NetBSD: psshfs.c,v 1.50 2009/02/23 18:43:46 pooka Exp $"); 44__RCSID("$NetBSD: psshfs.c,v 1.51 2009/05/20 13:56:36 pooka Exp $");
45#endif /* !lint */ 45#endif /* !lint */
46 46
47#include <sys/types.h> 47#include <sys/types.h>
48 48
49#include <assert.h> 49#include <assert.h>
50#include <err.h> 50#include <err.h>
51#include <errno.h> 51#include <errno.h>
52#include <mntopts.h> 52#include <mntopts.h>
53#include <paths.h> 53#include <paths.h>
54#include <poll.h> 54#include <poll.h>
55#include <puffs.h> 55#include <puffs.h>
56#include <signal.h> 56#include <signal.h>
57#include <stdlib.h> 57#include <stdlib.h>
58#include <util.h> 58#include <util.h>
59#include <unistd.h> 59#include <unistd.h>
60 60
61#include "psshfs.h" 61#include "psshfs.h"
62 62
63static int pssh_connect(struct psshfs_ctx *); 63static int pssh_connect(struct puffs_usermount *, int);
64static void psshfs_loopfn(struct puffs_usermount *); 64static void psshfs_loopfn(struct puffs_usermount *);
65static void usage(void); 65static void usage(void);
66static void add_ssharg(char ***, int *, char *); 66static void add_ssharg(char ***, int *, char *);
67static void psshfs_notify(struct puffs_usermount *, int, int); 67static void psshfs_notify(struct puffs_usermount *, int, int);
68 68
69#define SSH_PATH "/usr/bin/ssh" 69#define SSH_PATH "/usr/bin/ssh"
70 70
71unsigned int max_reads; 71unsigned int max_reads;
72static int sighup; 72static int sighup;
73 73
74static void 74static void
75add_ssharg(char ***sshargs, int *nargs, char *arg) 75add_ssharg(char ***sshargs, int *nargs, char *arg)
76{ 76{
77  77
78 *sshargs = realloc(*sshargs, (*nargs + 2) * sizeof(char*)); 78 *sshargs = realloc(*sshargs, (*nargs + 2) * sizeof(char*));
79 if (!*sshargs) 79 if (!*sshargs)
80 err(1, "realloc"); 80 err(1, "realloc");
81 (*sshargs)[(*nargs)++] = arg; 81 (*sshargs)[(*nargs)++] = arg;
82 (*sshargs)[*nargs] = NULL; 82 (*sshargs)[*nargs] = NULL;
83} 83}
84 84
85static void 85static void
86usage() 86usage()
87{ 87{
88 88
89 fprintf(stderr, "usage: %s " 89 fprintf(stderr, "usage: %s "
90 "[-es] [-F configfile] [-O sshopt=value] [-o opts] " 90 "[-ceprst] [-F configfile] [-O sshopt=value] [-o opts] "
91 "user@host:path mountpath\n", 91 "user@host:path mountpath\n",
92 getprogname()); 92 getprogname());
93 exit(1); 93 exit(1);
94} 94}
95 95
96static void 96static void
97takehup(int sig) 97takehup(int sig)
98{ 98{
99 99
100 sighup = 1; 100 sighup = 1;
101} 101}
102 102
103int 103int
@@ -106,45 +106,55 @@ main(int argc, char *argv[]) @@ -106,45 +106,55 @@ main(int argc, char *argv[])
106 struct psshfs_ctx pctx; 106 struct psshfs_ctx pctx;
107 struct puffs_usermount *pu; 107 struct puffs_usermount *pu;
108 struct puffs_ops *pops; 108 struct puffs_ops *pops;
109 struct psshfs_node *root = &pctx.psn_root; 109 struct psshfs_node *root = &pctx.psn_root;
110 struct puffs_node *pn_root; 110 struct puffs_node *pn_root;
111 puffs_framev_fdnotify_fn notfn; 111 puffs_framev_fdnotify_fn notfn;
112 struct vattr *rva; 112 struct vattr *rva;
113 mntoptparse_t mp; 113 mntoptparse_t mp;
114 char **sshargs; 114 char **sshargs;
115 char *userhost; 115 char *userhost;
116 char *hostpath; 116 char *hostpath;
117 int mntflags, pflags, ch; 117 int mntflags, pflags, ch;
118 int detach; 118 int detach;
119 int exportfs, refreshival; 119 int exportfs, refreshival, numconnections;
120 int nargs, x; 120 int nargs;
121 121
122 setprogname(argv[0]); 122 setprogname(argv[0]);
123 123
124 if (argc < 3) 124 if (argc < 3)
125 usage(); 125 usage();
126 126
127 mntflags = pflags = exportfs = nargs = 0; 127 mntflags = pflags = exportfs = nargs = 0;
 128 numconnections = 1;
128 detach = 1; 129 detach = 1;
129 refreshival = DEFAULTREFRESH; 130 refreshival = DEFAULTREFRESH;
130 notfn = puffs_framev_unmountonclose; 131 notfn = puffs_framev_unmountonclose;
131 sshargs = NULL; 132 sshargs = NULL;
132 add_ssharg(&sshargs, &nargs, SSH_PATH); 133 add_ssharg(&sshargs, &nargs, SSH_PATH);
133 add_ssharg(&sshargs, &nargs, "-axs"); 134 add_ssharg(&sshargs, &nargs, "-axs");
134 add_ssharg(&sshargs, &nargs, "-oClearAllForwardings=yes"); 135 add_ssharg(&sshargs, &nargs, "-oClearAllForwardings=yes");
135 136
136 while ((ch = getopt(argc, argv, "eF:o:O:pr:st:")) != -1) { 137 while ((ch = getopt(argc, argv, "c:eF:o:O:pr:st:")) != -1) {
137 switch (ch) { 138 switch (ch) {
 139 case 'c':
 140 numconnections = atoi(optarg);
 141 if (numconnections < 1 || numconnections > 2) {
 142 fprintf(stderr, "%s: only 1 or 2 connections "
 143 "permitted currently\n", getprogname());
 144 usage();
 145 /*NOTREACHED*/
 146 }
 147 break;
138 case 'e': 148 case 'e':
139 exportfs = 1; 149 exportfs = 1;
140 break; 150 break;
141 case 'F': 151 case 'F':
142 add_ssharg(&sshargs, &nargs, "-F"); 152 add_ssharg(&sshargs, &nargs, "-F");
143 add_ssharg(&sshargs, &nargs, optarg); 153 add_ssharg(&sshargs, &nargs, optarg);
144 break; 154 break;
145 case 'O': 155 case 'O':
146 add_ssharg(&sshargs, &nargs, "-o"); 156 add_ssharg(&sshargs, &nargs, "-o");
147 add_ssharg(&sshargs, &nargs, optarg); 157 add_ssharg(&sshargs, &nargs, optarg);
148 break; 158 break;
149 case 'o': 159 case 'o':
150 mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags); 160 mp = getmntopts(optarg, puffsmopts, &mntflags, &pflags);
@@ -204,171 +214,201 @@ main(int argc, char *argv[]) @@ -204,171 +214,201 @@ main(int argc, char *argv[])
204 PUFFSOP_SET(pops, psshfs, node, symlink); 214 PUFFSOP_SET(pops, psshfs, node, symlink);
205 PUFFSOP_SET(pops, psshfs, node, rename); 215 PUFFSOP_SET(pops, psshfs, node, rename);
206 PUFFSOP_SET(pops, psshfs, node, read); 216 PUFFSOP_SET(pops, psshfs, node, read);
207 PUFFSOP_SET(pops, psshfs, node, write); 217 PUFFSOP_SET(pops, psshfs, node, write);
208 PUFFSOP_SET(pops, psshfs, node, reclaim); 218 PUFFSOP_SET(pops, psshfs, node, reclaim);
209 219
210 pu = puffs_init(pops, argv[0], "psshfs", &pctx, pflags); 220 pu = puffs_init(pops, argv[0], "psshfs", &pctx, pflags);
211 if (pu == NULL) 221 if (pu == NULL)
212 err(1, "puffs_init"); 222 err(1, "puffs_init");
213 223
214 memset(&pctx, 0, sizeof(pctx)); 224 memset(&pctx, 0, sizeof(pctx));
215 pctx.mounttime = time(NULL); 225 pctx.mounttime = time(NULL);
216 pctx.refreshival = refreshival; 226 pctx.refreshival = refreshival;
 227 pctx.numconnections = numconnections;
217 228
218 userhost = argv[0]; 229 userhost = argv[0];
219 hostpath = strchr(userhost, ':'); 230 hostpath = strchr(userhost, ':');
220 if (hostpath) { 231 if (hostpath) {
221 *hostpath++ = '\0'; 232 *hostpath++ = '\0';
222 pctx.mountpath = hostpath; 233 pctx.mountpath = hostpath;
223 } else 234 } else
224 pctx.mountpath = "."; 235 pctx.mountpath = ".";
225 236
226 add_ssharg(&sshargs, &nargs, argv[0]); 237 add_ssharg(&sshargs, &nargs, argv[0]);
227 add_ssharg(&sshargs, &nargs, "sftp"); 238 add_ssharg(&sshargs, &nargs, "sftp");
228 pctx.sshargs = sshargs; 239 pctx.sshargs = sshargs;
229 240
230 pctx.nextino = 2; 241 pctx.nextino = 2;
231 memset(root, 0, sizeof(struct psshfs_node)); 242 memset(root, 0, sizeof(struct psshfs_node));
232 pn_root = puffs_pn_new(pu, root); 243 pn_root = puffs_pn_new(pu, root);
233 if (pn_root == NULL) 244 if (pn_root == NULL)
234 return errno; 245 return errno;
235 puffs_setroot(pu, pn_root); 246 puffs_setroot(pu, pn_root);
236 247
 248 puffs_framev_init(pu, psbuf_read, psbuf_write, psbuf_cmp, NULL, notfn);
 249
237 signal(SIGHUP, takehup); 250 signal(SIGHUP, takehup);
238 puffs_ml_setloopfn(pu, psshfs_loopfn); 251 puffs_ml_setloopfn(pu, psshfs_loopfn);
239 if (pssh_connect(&pctx) == -1) 252 if (pssh_connect(pu, PSSHFD_META) == -1)
240 err(1, "can't connect"); 253 err(1, "can't connect meta");
 254 if (puffs_framev_addfd(pu, pctx.sshfd,
 255 PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1)
 256 err(1, "framebuf addfd meta");
 257 if (numconnections == 2) {
 258 if (pssh_connect(pu, PSSHFD_DATA) == -1)
 259 err(1, "can't connect data");
 260 if (puffs_framev_addfd(pu, pctx.sshfd_data,
 261 PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1)
 262 err(1, "framebuf addfd data");
 263 } else {
 264 pctx.sshfd_data = pctx.sshfd;
 265 }
241 266
242 if (exportfs) 267 if (exportfs)
243 puffs_setfhsize(pu, sizeof(struct psshfs_fid), 268 puffs_setfhsize(pu, sizeof(struct psshfs_fid),
244 PUFFS_FHFLAG_NFSV2 | PUFFS_FHFLAG_NFSV3); 269 PUFFS_FHFLAG_NFSV2 | PUFFS_FHFLAG_NFSV3);
245 270
246 if (psshfs_handshake(pu) != 0) 
247 errx(1, "psshfs_handshake"); 
248 x = 1; 
249 if (ioctl(pctx.sshfd, FIONBIO, &x) == -1) 
250 err(1, "nonblocking descriptor"); 
251 
252 puffs_framev_init(pu, psbuf_read, psbuf_write, psbuf_cmp, NULL, notfn); 
253 if (puffs_framev_addfd(pu, pctx.sshfd, 
254 PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1) 
255 err(1, "framebuf addfd"); 
256 
257 rva = &pn_root->pn_va; 271 rva = &pn_root->pn_va;
258 rva->va_fileid = pctx.nextino++; 272 rva->va_fileid = pctx.nextino++;
259 rva->va_nlink = 101; /* XXX */ 273 rva->va_nlink = 101; /* XXX */
260 274
261 if (detach) 275 if (detach)
262 if (puffs_daemon(pu, 1, 1) == -1) 276 if (puffs_daemon(pu, 1, 1) == -1)
263 err(1, "puffs_daemon"); 277 err(1, "puffs_daemon");
264 278
265 if (puffs_mount(pu, argv[1], mntflags, puffs_getroot(pu)) == -1) 279 if (puffs_mount(pu, argv[1], mntflags, puffs_getroot(pu)) == -1)
266 err(1, "puffs_mount"); 280 err(1, "puffs_mount");
267 if (puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK) == -1) 281 if (puffs_setblockingmode(pu, PUFFSDEV_NONBLOCK) == -1)
268 err(1, "setblockingmode"); 282 err(1, "setblockingmode");
269 283
270 if (puffs_mainloop(pu) == -1) 284 if (puffs_mainloop(pu) == -1)
271 err(1, "mainloop"); 285 err(1, "mainloop");
272 puffs_exit(pu, 1); 286 puffs_exit(pu, 1);
273 287
274 return 0; 288 return 0;
275} 289}
276 290
277#define RETRY_MAX 100 291#define RETRY_MAX 100
278 292
279void 293void
280psshfs_notify(struct puffs_usermount *pu, int fd, int what) 294psshfs_notify(struct puffs_usermount *pu, int fd, int what)
281{ 295{
282 struct psshfs_ctx *pctx = puffs_getspecific(pu); 296 struct psshfs_ctx *pctx = puffs_getspecific(pu);
283 int x, nretry; 297 int x, nretry, which, newfd;
 298
 299 if (fd == pctx->sshfd) {
 300 which = PSSHFD_META;
 301 } else {
 302 assert(fd == pctx->sshfd_data);
 303 which = PSSHFD_DATA;
 304 }
284 305
285 if (puffs_getstate(pu) != PUFFS_STATE_RUNNING) 306 if (puffs_getstate(pu) != PUFFS_STATE_RUNNING)
286 return; 307 return;
287 308
288 if (what != (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) { 309 if (what != (PUFFS_FBIO_READ | PUFFS_FBIO_WRITE)) {
289 puffs_framev_removefd(pu, pctx->sshfd, ECONNRESET); 310 puffs_framev_removefd(pu, fd, ECONNRESET);
290 return; 311 return;
291 } 312 }
292 close(pctx->sshfd); 313 close(fd);
293 314
294 for (nretry = 0;;nretry++) { 315 for (nretry = 0;;nretry++) {
295 if (pssh_connect(pctx) == -1) 316 if ((newfd = pssh_connect(pu, which)) == -1)
296 goto retry2; 317 goto retry2;
297 318
298 if (psshfs_handshake(pu) != 0) 319 if (psshfs_handshake(pu, newfd) != 0)
299 goto retry1; 320 goto retry1;
300 321
301 x = 1; 322 x = 1;
302 if (ioctl(pctx->sshfd, FIONBIO, &x) == -1) 323 if (ioctl(newfd, FIONBIO, &x) == -1)
303 goto retry1; 324 goto retry1;
304 325
305 if (puffs_framev_addfd(pu, pctx->sshfd, 326 if (puffs_framev_addfd(pu, newfd,
306 PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1) 327 PUFFS_FBIO_READ | PUFFS_FBIO_WRITE) == -1)
307 goto retry1; 328 goto retry1;
308 329
309 break; 330 break;
310 retry1: 331 retry1:
311 fprintf(stderr, "reconnect failed... "); 332 fprintf(stderr, "reconnect failed... ");
312 close(pctx->sshfd); 333 close(newfd);
313 retry2: 334 retry2:
314 if (nretry < RETRY_MAX) { 335 if (nretry < RETRY_MAX) {
315 fprintf(stderr, "retrying\n"); 336 fprintf(stderr, "retrying\n");
316 sleep(nretry); 337 sleep(nretry);
317 } else { 338 } else {
318 fprintf(stderr, "retry count exceeded, going south\n"); 339 fprintf(stderr, "retry count exceeded, going south\n");
319 exit(1); /* XXXXXXX */ 340 exit(1); /* XXXXXXX */
320 } 341 }
321 } 342 }
322} 343}
323 344
324static int 345static int
325pssh_connect(struct psshfs_ctx *pctx) 346pssh_connect(struct puffs_usermount *pu, int which)
326{ 347{
 348 struct psshfs_ctx *pctx = puffs_getspecific(pu);
327 char **sshargs = pctx->sshargs; 349 char **sshargs = pctx->sshargs;
328 int fds[2]; 350 int fds[2];
329 pid_t pid; 351 pid_t pid;
330 int dnfd; 352 int dnfd, x;
 353 int *sshfd;
 354 pid_t *sshpid;
 355
 356 if (which == PSSHFD_META) {
 357 sshfd = &pctx->sshfd;
 358 sshpid = &pctx->sshpid;
 359 } else {
 360 assert(which == PSSHFD_DATA);
 361 sshfd = &pctx->sshfd_data;
 362 sshpid = &pctx->sshpid_data;
 363 }
331 364
332 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1) 365 if (socketpair(AF_UNIX, SOCK_STREAM, 0, fds) == -1)
333 return -1; 366 return -1;
334 367
335 pid = fork(); 368 pid = fork();
336 switch (pid) { 369 switch (pid) {
337 case -1: 370 case -1:
338 return -1; 371 return -1;
339 /*NOTREACHED*/ 372 /*NOTREACHED*/
340 case 0: /* child */ 373 case 0: /* child */
341 if (dup2(fds[0], STDIN_FILENO) == -1) 374 if (dup2(fds[0], STDIN_FILENO) == -1)
342 err(1, "child dup2"); 375 err(1, "child dup2");
343 if (dup2(fds[0], STDOUT_FILENO) == -1) 376 if (dup2(fds[0], STDOUT_FILENO) == -1)
344 err(1, "child dup2"); 377 err(1, "child dup2");
345 close(fds[0]); 378 close(fds[0]);
346 close(fds[1]); 379 close(fds[1]);
347 380
348 dnfd = open(_PATH_DEVNULL, O_RDWR); 381 dnfd = open(_PATH_DEVNULL, O_RDWR);
349 if (dnfd != -1) 382 if (dnfd != -1)
350 dup2(dnfd, STDERR_FILENO); 383 dup2(dnfd, STDERR_FILENO);
351 384
352 execvp(sshargs[0], sshargs); 385 execvp(sshargs[0], sshargs);
 386 /*NOTREACHED*/
353 break; 387 break;
354 default: 388 default:
355 pctx->sshpid = pid; 389 *sshpid = pid;
356 pctx->sshfd = fds[1]; 390 *sshfd = fds[1];
357 close(fds[0]); 391 close(fds[0]);
358 break; 392 break;
359 } 393 }
360 394
361 return 0; 395 if (psshfs_handshake(pu, *sshfd) != 0)
 396 errx(1, "psshfs_handshake %d", which);
 397 x = 1;
 398 if (ioctl(*sshfd, FIONBIO, &x) == -1)
 399 err(1, "nonblocking descriptor %d", which);
 400
 401 return *sshfd;
362} 402}
363 403
364static void * 404static void *
365invalone(struct puffs_usermount *pu, struct puffs_node *pn, void *arg) 405invalone(struct puffs_usermount *pu, struct puffs_node *pn, void *arg)
366{ 406{
367 struct psshfs_node *psn = pn->pn_data; 407 struct psshfs_node *psn = pn->pn_data;
368 408
369 psn->attrread = 0; 409 psn->attrread = 0;
370 psn->dentread = 0; 410 psn->dentread = 0;
371 psn->slread = 0; 411 psn->slread = 0;
372 412
373 return NULL; 413 return NULL;
374} 414}

cvs diff -r1.35 -r1.36 src/usr.sbin/puffs/mount_psshfs/psshfs.h (expand / switch to unified diff)

--- src/usr.sbin/puffs/mount_psshfs/psshfs.h 2009/02/23 18:43:46 1.35
+++ src/usr.sbin/puffs/mount_psshfs/psshfs.h 2009/05/20 13:56:36 1.36
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: psshfs.h,v 1.35 2009/02/23 18:43:46 pooka Exp $ */ 1/* $NetBSD: psshfs.h,v 1.36 2009/05/20 13:56:36 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006, 2007 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2006, 2007 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -55,45 +55,45 @@ PUFFSOP_PROTOS(psshfs); @@ -55,45 +55,45 @@ PUFFSOP_PROTOS(psshfs);
55 55
56#define NEXTREQ(pctx) ((pctx->nextreq)++) 56#define NEXTREQ(pctx) ((pctx->nextreq)++)
57#define PSSHFSAUTOVAR(pu) \ 57#define PSSHFSAUTOVAR(pu) \
58 struct puffs_cc *pcc = puffs_cc_getcc(pu); \ 58 struct puffs_cc *pcc = puffs_cc_getcc(pu); \
59 struct psshfs_ctx *pctx = puffs_getspecific(pu); \ 59 struct psshfs_ctx *pctx = puffs_getspecific(pu); \
60 uint32_t reqid = NEXTREQ(pctx); \ 60 uint32_t reqid = NEXTREQ(pctx); \
61 struct puffs_framebuf *pb = psbuf_makeout(); \ 61 struct puffs_framebuf *pb = psbuf_makeout(); \
62 int rv = 0 62 int rv = 0
63 63
64#define PSSHFSRETURN(rv) \ 64#define PSSHFSRETURN(rv) \
65 puffs_framebuf_destroy(pb); \ 65 puffs_framebuf_destroy(pb); \
66 return (rv) 66 return (rv)
67 67
68#define GETRESPONSE(pb) \ 68#define GETRESPONSE(pb, fd) \
69do { \ 69do { \
70 if (puffs_framev_enqueue_cc(pcc, pctx->sshfd, pb, 0) == -1) { \ 70 if (puffs_framev_enqueue_cc(pcc, fd, pb, 0) == -1) { \
71 rv = errno; \ 71 rv = errno; \
72 goto out; \ 72 goto out; \
73 } \ 73 } \
74} while (/*CONSTCOND*/0) 74} while (/*CONSTCOND*/0)
75 75
76#define JUSTSEND(pb) \ 76#define JUSTSEND(pb,fd) \
77do { \ 77do { \
78 if (puffs_framev_enqueue_justsend(pu,pctx->sshfd,pb,1,0) == -1){\ 78 if (puffs_framev_enqueue_justsend(pu, fd, pb, 1, 0) == -1) { \
79 rv = errno; \ 79 rv = errno; \
80 goto out; \ 80 goto out; \
81 } \ 81 } \
82} while (/*CONSTCOND*/0) 82} while (/*CONSTCOND*/0)
83 83
84#define SENDCB(pb, f, a) \ 84#define SENDCB(pb, fd, f, a) \
85do { \ 85do { \
86 if (puffs_framev_enqueue_cb(pu, pctx->sshfd, pb,f,a,0) == -1) { \ 86 if (puffs_framev_enqueue_cb(pu, fd, pb, f, a, 0) == -1) { \
87 rv = errno; \ 87 rv = errno; \
88 goto out; \ 88 goto out; \
89 } \ 89 } \
90} while (/*CONSTCOND*/0) 90} while (/*CONSTCOND*/0)
91 91
92struct psshfs_dir { 92struct psshfs_dir {
93 int valid; 93 int valid;
94 struct puffs_node *entry; 94 struct puffs_node *entry;
95 95
96 char *entryname; 96 char *entryname;
97 struct vattr va; 97 struct vattr va;
98 time_t attrread; 98 time_t attrread;
99}; 99};
@@ -143,48 +143,54 @@ struct psshfs_node { @@ -143,48 +143,54 @@ struct psshfs_node {
143#define PSN_RECLAIMED 0x01 143#define PSN_RECLAIMED 0x01
144#define PSN_HASFH 0x02 144#define PSN_HASFH 0x02
145#define PSN_READDIR 0x04 145#define PSN_READDIR 0x04
146#define PSN_DOLAZY_R 0x08 146#define PSN_DOLAZY_R 0x08
147#define PSN_DOLAZY_W 0x10 147#define PSN_DOLAZY_W 0x10
148#define PSN_LAZYWAIT_R 0x20 148#define PSN_LAZYWAIT_R 0x20
149#define PSN_LAZYWAIT_W 0x40 149#define PSN_LAZYWAIT_W 0x40
150#define PSN_HANDLECLOSE 0x80 150#define PSN_HANDLECLOSE 0x80
151 151
152#define HANDLE_READ 0x1 152#define HANDLE_READ 0x1
153#define HANDLE_WRITE 0x2 153#define HANDLE_WRITE 0x2
154 154
155struct psshfs_ctx { 155struct psshfs_ctx {
 156 int numconnections;
156 int sshfd; 157 int sshfd;
 158 int sshfd_data;
157 pid_t sshpid; 159 pid_t sshpid;
 160 pid_t sshpid_data;
 161
158 const char *mountpath; 162 const char *mountpath;
159 char **sshargs; 163 char **sshargs;
160 164
161 int protover; 165 int protover;
162 int extensions; 166 int extensions;
163 167
164 uint32_t nextreq; 168 uint32_t nextreq;
165 169
166 struct puffs_framebuf *curpb; 170 struct puffs_framebuf *curpb;
167 171
168 struct psshfs_node psn_root; 172 struct psshfs_node psn_root;
169 ino_t nextino; 173 ino_t nextino;
170 174
171 int canexport; 175 int canexport;
172 time_t mounttime; 176 time_t mounttime;
173 177
174 int refreshival; 178 int refreshival;
175}; 179};
 180#define PSSHFD_META 0
 181#define PSSHFD_DATA 1
176 182
177int psshfs_handshake(struct puffs_usermount *); 183int psshfs_handshake(struct puffs_usermount *, int);
178 184
179int psbuf_read(struct puffs_usermount *, struct puffs_framebuf *,int,int*); 185int psbuf_read(struct puffs_usermount *, struct puffs_framebuf *,int,int*);
180int psbuf_write(struct puffs_usermount *, struct puffs_framebuf *,int,int*); 186int psbuf_write(struct puffs_usermount *, struct puffs_framebuf *,int,int*);
181int psbuf_cmp(struct puffs_usermount *, 187int psbuf_cmp(struct puffs_usermount *,
182 struct puffs_framebuf *, struct puffs_framebuf *, int *); 188 struct puffs_framebuf *, struct puffs_framebuf *, int *);
183 189
184struct puffs_framebuf *psbuf_makeout(void); 190struct puffs_framebuf *psbuf_makeout(void);
185void psbuf_recycleout(struct puffs_framebuf *); 191void psbuf_recycleout(struct puffs_framebuf *);
186 192
187void psbuf_put_1(struct puffs_framebuf *, uint8_t); 193void psbuf_put_1(struct puffs_framebuf *, uint8_t);
188void psbuf_put_2(struct puffs_framebuf *, uint16_t); 194void psbuf_put_2(struct puffs_framebuf *, uint16_t);
189void psbuf_put_4(struct puffs_framebuf *, uint32_t); 195void psbuf_put_4(struct puffs_framebuf *, uint32_t);
190void psbuf_put_8(struct puffs_framebuf *, uint64_t); 196void psbuf_put_8(struct puffs_framebuf *, uint64_t);

cvs diff -r1.45 -r1.46 src/usr.sbin/puffs/mount_psshfs/subr.c (expand / switch to unified diff)

--- src/usr.sbin/puffs/mount_psshfs/subr.c 2007/12/13 14:59:00 1.45
+++ src/usr.sbin/puffs/mount_psshfs/subr.c 2009/05/20 13:56:36 1.46
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: subr.c,v 1.45 2007/12/13 14:59:00 pooka Exp $ */ 1/* $NetBSD: subr.c,v 1.46 2009/05/20 13:56:36 pooka Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved. 4 * Copyright (c) 2006 Antti Kantee. All Rights Reserved.
5 * 5 *
6 * Redistribution and use in source and binary forms, with or without 6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions 7 * modification, are permitted provided that the following conditions
8 * are met: 8 * are met:
9 * 1. Redistributions of source code must retain the above copyright 9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer. 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright 11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the 12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution. 13 * documentation and/or other materials provided with the distribution.
14 * 14 *
@@ -17,27 +17,27 @@ @@ -17,27 +17,27 @@
17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE 17 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE. 25 * SUCH DAMAGE.
26 */ 26 */
27 27
28#include <sys/cdefs.h> 28#include <sys/cdefs.h>
29#ifndef lint 29#ifndef lint
30__RCSID("$NetBSD: subr.c,v 1.45 2007/12/13 14:59:00 pooka Exp $"); 30__RCSID("$NetBSD: subr.c,v 1.46 2009/05/20 13:56:36 pooka Exp $");
31#endif /* !lint */ 31#endif /* !lint */
32 32
33#include <assert.h> 33#include <assert.h>
34#include <err.h> 34#include <err.h>
35#include <errno.h> 35#include <errno.h>
36#include <puffs.h> 36#include <puffs.h>
37#include <stdlib.h> 37#include <stdlib.h>
38#include <util.h> 38#include <util.h>
39 39
40#include "psshfs.h" 40#include "psshfs.h"
41#include "sftp_proto.h" 41#include "sftp_proto.h"
42 42
43static void 43static void
@@ -124,39 +124,39 @@ void @@ -124,39 +124,39 @@ void
124closehandles(struct puffs_usermount *pu, struct psshfs_node *psn, int which) 124closehandles(struct puffs_usermount *pu, struct psshfs_node *psn, int which)
125{ 125{
126 struct psshfs_ctx *pctx = puffs_getspecific(pu); 126 struct psshfs_ctx *pctx = puffs_getspecific(pu);
127 struct puffs_framebuf *pb1, *pb2; 127 struct puffs_framebuf *pb1, *pb2;
128 uint32_t reqid; 128 uint32_t reqid;
129 129
130 if (psn->fhand_r && (which & HANDLE_READ)) { 130 if (psn->fhand_r && (which & HANDLE_READ)) {
131 assert(psn->lazyopen_r == NULL); 131 assert(psn->lazyopen_r == NULL);
132 132
133 pb1 = psbuf_makeout(); 133 pb1 = psbuf_makeout();
134 reqid = NEXTREQ(pctx); 134 reqid = NEXTREQ(pctx);
135 psbuf_req_data(pb1, SSH_FXP_CLOSE, reqid, 135 psbuf_req_data(pb1, SSH_FXP_CLOSE, reqid,
136 psn->fhand_r, psn->fhand_r_len); 136 psn->fhand_r, psn->fhand_r_len);
137 puffs_framev_enqueue_justsend(pu, pctx->sshfd, pb1, 1, 0); 137 puffs_framev_enqueue_justsend(pu, pctx->sshfd_data, pb1, 1, 0);
138 free(psn->fhand_r); 138 free(psn->fhand_r);
139 psn->fhand_r = NULL; 139 psn->fhand_r = NULL;
140 } 140 }
141 141
142 if (psn->fhand_w && (which & HANDLE_WRITE)) { 142 if (psn->fhand_w && (which & HANDLE_WRITE)) {
143 assert(psn->lazyopen_w == NULL); 143 assert(psn->lazyopen_w == NULL);
144 144
145 pb2 = psbuf_makeout(); 145 pb2 = psbuf_makeout();
146 reqid = NEXTREQ(pctx); 146 reqid = NEXTREQ(pctx);
147 psbuf_req_data(pb2, SSH_FXP_CLOSE, reqid, 147 psbuf_req_data(pb2, SSH_FXP_CLOSE, reqid,
148 psn->fhand_w, psn->fhand_w_len); 148 psn->fhand_w, psn->fhand_w_len);
149 puffs_framev_enqueue_justsend(pu, pctx->sshfd, pb2, 1, 0); 149 puffs_framev_enqueue_justsend(pu, pctx->sshfd_data, pb2, 1, 0);
150 free(psn->fhand_w); 150 free(psn->fhand_w);
151 psn->fhand_w = NULL; 151 psn->fhand_w = NULL;
152 } 152 }
153 153
154 psn->stat |= PSN_HANDLECLOSE; 154 psn->stat |= PSN_HANDLECLOSE;
155} 155}
156 156
157void 157void
158lazyopen_rresp(struct puffs_usermount *pu, struct puffs_framebuf *pb, 158lazyopen_rresp(struct puffs_usermount *pu, struct puffs_framebuf *pb,
159 void *arg, int error) 159 void *arg, int error)
160{ 160{
161 struct psshfs_node *psn = arg; 161 struct psshfs_node *psn = arg;
162 162
@@ -210,27 +210,27 @@ lazyopen_wresp(struct puffs_usermount *p @@ -210,27 +210,27 @@ lazyopen_wresp(struct puffs_usermount *p
210 210
211struct readdirattr { 211struct readdirattr {
212 struct psshfs_node *psn; 212 struct psshfs_node *psn;
213 int idx; 213 int idx;
214 char entryname[MAXPATHLEN+1]; 214 char entryname[MAXPATHLEN+1];
215}; 215};
216 216
217int 217int
218getpathattr(struct puffs_usermount *pu, const char *path, struct vattr *vap) 218getpathattr(struct puffs_usermount *pu, const char *path, struct vattr *vap)
219{ 219{
220 PSSHFSAUTOVAR(pu); 220 PSSHFSAUTOVAR(pu);
221 221
222 psbuf_req_str(pb, SSH_FXP_LSTAT, reqid, path); 222 psbuf_req_str(pb, SSH_FXP_LSTAT, reqid, path);
223 GETRESPONSE(pb); 223 GETRESPONSE(pb, pctx->sshfd);
224 224
225 rv = psbuf_expect_attrs(pb, vap); 225 rv = psbuf_expect_attrs(pb, vap);
226 226
227 out: 227 out:
228 PSSHFSRETURN(rv); 228 PSSHFSRETURN(rv);
229} 229}
230 230
231int 231int
232getnodeattr(struct puffs_usermount *pu, struct puffs_node *pn) 232getnodeattr(struct puffs_usermount *pu, struct puffs_node *pn)
233{ 233{
234 struct psshfs_ctx *pctx = puffs_getspecific(pu); 234 struct psshfs_ctx *pctx = puffs_getspecific(pu);
235 struct psshfs_node *psn = pn->pn_data; 235 struct psshfs_node *psn = pn->pn_data;
236 struct vattr va; 236 struct vattr va;
@@ -297,27 +297,27 @@ sftp_readdir(struct puffs_usermount *pu, @@ -297,27 +297,27 @@ sftp_readdir(struct puffs_usermount *pu,
297 * large directories might expire before the directory itself and 297 * large directories might expire before the directory itself and
298 * result in one-by-one attribute fetching. 298 * result in one-by-one attribute fetching.
299 */ 299 */
300 psn->dentread = time(NULL); 300 psn->dentread = time(NULL);
301 301
302 psn->dentnext = 0; 302 psn->dentnext = 0;
303 psn->denttot = 0; 303 psn->denttot = 0;
304 psn->dir = NULL; 304 psn->dir = NULL;
305 305
306 for (;;) { 306 for (;;) {
307 reqid = NEXTREQ(pctx); 307 reqid = NEXTREQ(pctx);
308 psbuf_recycleout(pb); 308 psbuf_recycleout(pb);
309 psbuf_req_data(pb, SSH_FXP_READDIR, reqid, dhand, dhandlen); 309 psbuf_req_data(pb, SSH_FXP_READDIR, reqid, dhand, dhandlen);
310 GETRESPONSE(pb); 310 GETRESPONSE(pb, pctx->sshfd);
311 311
312 /* check for EOF */ 312 /* check for EOF */
313 if (psbuf_get_type(pb) == SSH_FXP_STATUS) { 313 if (psbuf_get_type(pb) == SSH_FXP_STATUS) {
314 rv = psbuf_expect_status(pb); 314 rv = psbuf_expect_status(pb);
315 goto out; 315 goto out;
316 } 316 }
317 rv = psbuf_expect_name(pb, &count); 317 rv = psbuf_expect_name(pb, &count);
318 if (rv) 318 if (rv)
319 goto out; 319 goto out;
320 320
321 for (; count--; idx++) { 321 for (; count--; idx++) {
322 if (idx == psn->denttot) 322 if (idx == psn->denttot)
323 allocdirs(psn); 323 allocdirs(psn);