1 /* 2 * Copyright 2016 Jakub Klama <jceel@FreeBSD.org> 3 * All rights reserved 4 * 5 * Redistribution and use in source and binary forms, with or without 6 * modification, are permitted providing that the following conditions 7 * are met: 8 * 1. Redistributions of source code must retain the above copyright 9 * notice, this list of conditions and the following disclaimer. 10 * 2. Redistributions in binary form must reproduce the above copyright 11 * notice, this list of conditions and the following disclaimer in the 12 * documentation and/or other materials provided with the distribution. 13 * 14 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 15 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED 16 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY 18 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 22 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 23 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 24 * POSSIBILITY OF SUCH DAMAGE. 25 * 26 */ 27 28 #include <stdlib.h> 29 #include <string.h> 30 #include <assert.h> 31 #include <errno.h> 32 #include <sys/param.h> 33 #include <sys/uio.h> 34 #ifdef __illumos__ 35 #include <sys/sysmacros.h> 36 #endif 37 #if defined(__FreeBSD__) 38 #include <sys/sbuf.h> 39 #else 40 #include "sbuf/sbuf.h" 41 #endif 42 #include "lib9p.h" 43 #include "lib9p_impl.h" 44 #include "fcall.h" 45 #include "fid.h" 46 #include "hashtable.h" 47 #include "log.h" 48 #include "linux_errno.h" 49 #include "backend/backend.h" 50 #include "threadpool.h" 51 52 #define N(x) (sizeof(x) / sizeof(x[0])) 53 54 static int l9p_dispatch_tversion(struct l9p_request *req); 55 static int l9p_dispatch_tattach(struct l9p_request *req); 56 static int l9p_dispatch_tclunk(struct l9p_request *req); 57 static int l9p_dispatch_tcreate(struct l9p_request *req); 58 static int l9p_dispatch_topen(struct l9p_request *req); 59 static int l9p_dispatch_tread(struct l9p_request *req); 60 static int l9p_dispatch_tremove(struct l9p_request *req); 61 static int l9p_dispatch_tstat(struct l9p_request *req); 62 static int l9p_dispatch_twalk(struct l9p_request *req); 63 static int l9p_dispatch_twrite(struct l9p_request *req); 64 static int l9p_dispatch_twstat(struct l9p_request *req); 65 static int l9p_dispatch_tstatfs(struct l9p_request *req); 66 static int l9p_dispatch_tlopen(struct l9p_request *req); 67 static int l9p_dispatch_tlcreate(struct l9p_request *req); 68 static int l9p_dispatch_tsymlink(struct l9p_request *req); 69 static int l9p_dispatch_tmknod(struct l9p_request *req); 70 static int l9p_dispatch_trename(struct l9p_request *req); 71 static int l9p_dispatch_treadlink(struct l9p_request *req); 72 static int l9p_dispatch_tgetattr(struct l9p_request *req); 73 static int l9p_dispatch_tsetattr(struct l9p_request *req); 74 static int l9p_dispatch_txattrwalk(struct l9p_request *req); 75 static int l9p_dispatch_txattrcreate(struct l9p_request *req); 76 static int l9p_dispatch_treaddir(struct l9p_request *req); 77 static int l9p_dispatch_tfsync(struct l9p_request *req); 78 static int l9p_dispatch_tlock(struct l9p_request *req); 79 static int l9p_dispatch_tgetlock(struct l9p_request *req); 80 static int l9p_dispatch_tlink(struct l9p_request *req); 81 static int l9p_dispatch_tmkdir(struct l9p_request *req); 82 static int l9p_dispatch_trenameat(struct l9p_request *req); 83 static int l9p_dispatch_tunlinkat(struct l9p_request *req); 84 85 /* 86 * Each Txxx handler has a "must run" flag. If it is false, 87 * we check for a flush request before calling the handler. 88 * If a flush is already requested we can instantly fail the 89 * request with EINTR. 90 * 91 * Tclunk and Tremove must run because they make their fids 92 * become invalid. Tversion and Tattach should never get 93 * a flush request applied (it makes no sense as the connection 94 * is not really running yet), so it should be harmless to 95 * set them either way, but for now we have them as must-run. 96 * Flushing a Tflush is not really allowed either so we keep 97 * these as must-run too (although they run without being done 98 * threaded anyway). 99 */ 100 struct l9p_handler { 101 enum l9p_ftype type; 102 int (*handler)(struct l9p_request *); 103 bool must_run; 104 }; 105 106 static const struct l9p_handler l9p_handlers_no_version[] = { 107 {L9P_TVERSION, l9p_dispatch_tversion, true}, 108 }; 109 110 static const struct l9p_handler l9p_handlers_base[] = { 111 {L9P_TVERSION, l9p_dispatch_tversion, true}, 112 {L9P_TATTACH, l9p_dispatch_tattach, true}, 113 {L9P_TCLUNK, l9p_dispatch_tclunk, true}, 114 {L9P_TFLUSH, l9p_threadpool_tflush, true}, 115 {L9P_TCREATE, l9p_dispatch_tcreate, false}, 116 {L9P_TOPEN, l9p_dispatch_topen, false}, 117 {L9P_TREAD, l9p_dispatch_tread, false}, 118 {L9P_TWRITE, l9p_dispatch_twrite, false}, 119 {L9P_TREMOVE, l9p_dispatch_tremove, true}, 120 {L9P_TSTAT, l9p_dispatch_tstat, false}, 121 {L9P_TWALK, l9p_dispatch_twalk, false}, 122 {L9P_TWSTAT, l9p_dispatch_twstat, false} 123 }; 124 static const struct l9p_handler l9p_handlers_dotu[] = { 125 {L9P_TVERSION, l9p_dispatch_tversion, true}, 126 {L9P_TATTACH, l9p_dispatch_tattach, true}, 127 {L9P_TCLUNK, l9p_dispatch_tclunk, true}, 128 {L9P_TFLUSH, l9p_threadpool_tflush, true}, 129 {L9P_TCREATE, l9p_dispatch_tcreate, false}, 130 {L9P_TOPEN, l9p_dispatch_topen, false}, 131 {L9P_TREAD, l9p_dispatch_tread, false}, 132 {L9P_TWRITE, l9p_dispatch_twrite, false}, 133 {L9P_TREMOVE, l9p_dispatch_tremove, true}, 134 {L9P_TSTAT, l9p_dispatch_tstat, false}, 135 {L9P_TWALK, l9p_dispatch_twalk, false}, 136 {L9P_TWSTAT, l9p_dispatch_twstat, false} 137 }; 138 static const struct l9p_handler l9p_handlers_dotL[] = { 139 {L9P_TVERSION, l9p_dispatch_tversion, true}, 140 {L9P_TATTACH, l9p_dispatch_tattach, true}, 141 {L9P_TCLUNK, l9p_dispatch_tclunk, true}, 142 {L9P_TFLUSH, l9p_threadpool_tflush, true}, 143 {L9P_TCREATE, l9p_dispatch_tcreate, false}, 144 {L9P_TOPEN, l9p_dispatch_topen, false}, 145 {L9P_TREAD, l9p_dispatch_tread, false}, 146 {L9P_TWRITE, l9p_dispatch_twrite, false}, 147 {L9P_TREMOVE, l9p_dispatch_tremove, true}, 148 {L9P_TSTAT, l9p_dispatch_tstat, false}, 149 {L9P_TWALK, l9p_dispatch_twalk, false}, 150 {L9P_TWSTAT, l9p_dispatch_twstat, false}, 151 {L9P_TSTATFS, l9p_dispatch_tstatfs, false}, 152 {L9P_TLOPEN, l9p_dispatch_tlopen, false}, 153 {L9P_TLCREATE, l9p_dispatch_tlcreate, false}, 154 {L9P_TSYMLINK, l9p_dispatch_tsymlink, false}, 155 {L9P_TMKNOD, l9p_dispatch_tmknod, false}, 156 {L9P_TRENAME, l9p_dispatch_trename, false}, 157 {L9P_TREADLINK, l9p_dispatch_treadlink, false}, 158 {L9P_TGETATTR, l9p_dispatch_tgetattr, false}, 159 {L9P_TSETATTR, l9p_dispatch_tsetattr, false}, 160 {L9P_TXATTRWALK, l9p_dispatch_txattrwalk, false}, 161 {L9P_TXATTRCREATE, l9p_dispatch_txattrcreate, false}, 162 {L9P_TREADDIR, l9p_dispatch_treaddir, false}, 163 {L9P_TFSYNC, l9p_dispatch_tfsync, false}, 164 {L9P_TLOCK, l9p_dispatch_tlock, true}, 165 {L9P_TGETLOCK, l9p_dispatch_tgetlock, true}, 166 {L9P_TLINK, l9p_dispatch_tlink, false}, 167 {L9P_TMKDIR, l9p_dispatch_tmkdir, false}, 168 {L9P_TRENAMEAT, l9p_dispatch_trenameat, false}, 169 {L9P_TUNLINKAT, l9p_dispatch_tunlinkat, false}, 170 }; 171 172 /* 173 * NB: version index 0 is reserved for new connections, and 174 * is a protocol that handles only L9P_TVERSION. Once we get a 175 * valid version, we start a new session using its dispatch table. 176 */ 177 static const struct { 178 const char *name; 179 const struct l9p_handler *handlers; 180 int n_handlers; 181 } l9p_versions[] = { 182 { "<none>", l9p_handlers_no_version, N(l9p_handlers_no_version) }, 183 { "9P2000", l9p_handlers_base, N(l9p_handlers_base) }, 184 { "9P2000.u", l9p_handlers_dotu, N(l9p_handlers_dotu), }, 185 { "9P2000.L", l9p_handlers_dotL, N(l9p_handlers_dotL), }, 186 }; 187 188 /* 189 * Run the appropriate handler for this request. 190 * It's our caller's responsibility to respond. 191 */ 192 int 193 l9p_dispatch_request(struct l9p_request *req) 194 { 195 struct l9p_connection *conn; 196 #if defined(L9P_DEBUG) 197 struct sbuf *sb; 198 #endif 199 size_t i, n; 200 const struct l9p_handler *handlers, *hp; 201 bool flush_requested; 202 203 conn = req->lr_conn; 204 flush_requested = req->lr_flushstate == L9P_FLUSH_REQUESTED_PRE_START; 205 206 handlers = l9p_versions[conn->lc_version].handlers; 207 n = (size_t)l9p_versions[conn->lc_version].n_handlers; 208 for (hp = handlers, i = 0; i < n; hp++, i++) 209 if (req->lr_req.hdr.type == hp->type) 210 goto found; 211 hp = NULL; 212 found: 213 214 #if defined(L9P_DEBUG) 215 sb = sbuf_new_auto(); 216 if (flush_requested) { 217 sbuf_cat(sb, "FLUSH requested pre-dispatch"); 218 if (hp != NULL && hp->must_run) 219 sbuf_cat(sb, ", but must run"); 220 sbuf_cat(sb, ": "); 221 } 222 l9p_describe_fcall(&req->lr_req, conn->lc_version, sb); 223 sbuf_finish(sb); 224 225 L9P_LOG(L9P_DEBUG, "%s", sbuf_data(sb)); 226 sbuf_delete(sb); 227 #endif 228 229 if (hp != NULL) { 230 if (!flush_requested || hp->must_run) 231 return (hp->handler(req)); 232 return (EINTR); 233 } 234 235 L9P_LOG(L9P_WARNING, "unknown request of type %d", 236 req->lr_req.hdr.type); 237 return (ENOSYS); 238 } 239 240 /* 241 * Translate BSD errno to 9P2000/9P2000.u errno. 242 */ 243 static inline int 244 e29p(int errnum) 245 { 246 static int const table[] = { 247 [ENOTEMPTY] = EPERM, 248 [EDQUOT] = EPERM, 249 [ENOSYS] = EPERM, /* ??? */ 250 }; 251 252 if ((size_t)errnum < N(table) && table[errnum] != 0) 253 return (table[errnum]); 254 if (errnum <= ERANGE) 255 return (errnum); 256 return (EIO); /* ??? */ 257 } 258 259 /* 260 * Translate BSD errno to Linux errno. 261 */ 262 static inline int 263 e2linux(int errnum) 264 { 265 static int const table[] = { 266 [EDEADLK] = LINUX_EDEADLK, 267 [EAGAIN] = LINUX_EAGAIN, 268 [EINPROGRESS] = LINUX_EINPROGRESS, 269 [EALREADY] = LINUX_EALREADY, 270 [ENOTSOCK] = LINUX_ENOTSOCK, 271 [EDESTADDRREQ] = LINUX_EDESTADDRREQ, 272 [EMSGSIZE] = LINUX_EMSGSIZE, 273 [EPROTOTYPE] = LINUX_EPROTOTYPE, 274 [ENOPROTOOPT] = LINUX_ENOPROTOOPT, 275 [EPROTONOSUPPORT] = LINUX_EPROTONOSUPPORT, 276 [ESOCKTNOSUPPORT] = LINUX_ESOCKTNOSUPPORT, 277 [EOPNOTSUPP] = LINUX_EOPNOTSUPP, 278 [EPFNOSUPPORT] = LINUX_EPFNOSUPPORT, 279 [EAFNOSUPPORT] = LINUX_EAFNOSUPPORT, 280 [EADDRINUSE] = LINUX_EADDRINUSE, 281 [EADDRNOTAVAIL] = LINUX_EADDRNOTAVAIL, 282 [ENETDOWN] = LINUX_ENETDOWN, 283 [ENETUNREACH] = LINUX_ENETUNREACH, 284 [ENETRESET] = LINUX_ENETRESET, 285 [ECONNABORTED] = LINUX_ECONNABORTED, 286 [ECONNRESET] = LINUX_ECONNRESET, 287 [ENOBUFS] = LINUX_ENOBUFS, 288 [EISCONN] = LINUX_EISCONN, 289 [ENOTCONN] = LINUX_ENOTCONN, 290 [ESHUTDOWN] = LINUX_ESHUTDOWN, 291 [ETOOMANYREFS] = LINUX_ETOOMANYREFS, 292 [ETIMEDOUT] = LINUX_ETIMEDOUT, 293 [ECONNREFUSED] = LINUX_ECONNREFUSED, 294 [ELOOP] = LINUX_ELOOP, 295 [ENAMETOOLONG] = LINUX_ENAMETOOLONG, 296 [EHOSTDOWN] = LINUX_EHOSTDOWN, 297 [EHOSTUNREACH] = LINUX_EHOSTUNREACH, 298 [ENOTEMPTY] = LINUX_ENOTEMPTY, 299 #ifndef __illumos__ 300 [EPROCLIM] = LINUX_EAGAIN, 301 #endif 302 [EUSERS] = LINUX_EUSERS, 303 [EDQUOT] = LINUX_EDQUOT, 304 [ESTALE] = LINUX_ESTALE, 305 [EREMOTE] = LINUX_EREMOTE, 306 /* EBADRPC = unmappable? */ 307 /* ERPCMISMATCH = unmappable? */ 308 /* EPROGUNAVAIL = unmappable? */ 309 /* EPROGMISMATCH = unmappable? */ 310 /* EPROCUNAVAIL = unmappable? */ 311 [ENOLCK] = LINUX_ENOLCK, 312 [ENOSYS] = LINUX_ENOSYS, 313 /* EFTYPE = unmappable? */ 314 /* EAUTH = unmappable? */ 315 /* ENEEDAUTH = unmappable? */ 316 [EIDRM] = LINUX_EIDRM, 317 [ENOMSG] = LINUX_ENOMSG, 318 [EOVERFLOW] = LINUX_EOVERFLOW, 319 [ECANCELED] = LINUX_ECANCELED, 320 [EILSEQ] = LINUX_EILSEQ, 321 /* EDOOFUS = unmappable? */ 322 [EBADMSG] = LINUX_EBADMSG, 323 [EMULTIHOP] = LINUX_EMULTIHOP, 324 [ENOLINK] = LINUX_ENOLINK, 325 [EPROTO] = LINUX_EPROTO, 326 /* ENOTCAPABLE = unmappable? */ 327 #ifdef ECAPMODE 328 [ECAPMODE] = EPERM, 329 #endif 330 #ifdef ENOTRECOVERABLE 331 [ENOTRECOVERABLE] = LINUX_ENOTRECOVERABLE, 332 #endif 333 #ifdef EOWNERDEAD 334 [EOWNERDEAD] = LINUX_EOWNERDEAD, 335 #endif 336 }; 337 338 /* 339 * In case we want to return a raw Linux errno, allow negative 340 * values a la Linux kernel internals. 341 * 342 * Values up to ERANGE are shared across systems (see 343 * linux_errno.h), except for EAGAIN. 344 */ 345 if (errnum < 0) 346 return (-errnum); 347 348 if ((size_t)errnum < N(table) && table[errnum] != 0) 349 return (table[errnum]); 350 351 if (errnum <= ERANGE) 352 return (errnum); 353 354 L9P_LOG(L9P_WARNING, "cannot map errno %d to anything reasonable", 355 errnum); 356 357 return (LINUX_ENOTRECOVERABLE); /* ??? */ 358 } 359 360 /* 361 * Send response to request, or possibly just drop request. 362 * We also need to know whether to remove the request from 363 * the tag hash table. 364 */ 365 void 366 l9p_respond(struct l9p_request *req, bool drop, bool rmtag) 367 { 368 struct l9p_connection *conn = req->lr_conn; 369 size_t iosize; 370 #if defined(L9P_DEBUG) 371 struct sbuf *sb; 372 const char *ftype; 373 #endif 374 int error; 375 376 req->lr_resp.hdr.tag = req->lr_req.hdr.tag; 377 378 error = req->lr_error; 379 if (error == 0) 380 req->lr_resp.hdr.type = req->lr_req.hdr.type + 1; 381 else { 382 if (conn->lc_version == L9P_2000L) { 383 req->lr_resp.hdr.type = L9P_RLERROR; 384 req->lr_resp.error.errnum = (uint32_t)e2linux(error); 385 } else { 386 req->lr_resp.hdr.type = L9P_RERROR; 387 req->lr_resp.error.ename = strerror(error); 388 req->lr_resp.error.errnum = (uint32_t)e29p(error); 389 } 390 } 391 392 #if defined(L9P_DEBUG) 393 sb = sbuf_new_auto(); 394 l9p_describe_fcall(&req->lr_resp, conn->lc_version, sb); 395 sbuf_finish(sb); 396 397 switch (req->lr_flushstate) { 398 case L9P_FLUSH_NONE: 399 default: 400 ftype = ""; 401 break; 402 case L9P_FLUSH_REQUESTED_PRE_START: 403 ftype = "FLUSH requested pre-dispatch: "; 404 break; 405 case L9P_FLUSH_REQUESTED_POST_START: 406 ftype = "FLUSH requested while running: "; 407 break; 408 case L9P_FLUSH_TOOLATE: 409 ftype = "FLUSH requested too late: "; 410 break; 411 } 412 L9P_LOG(L9P_DEBUG, "%s%s%s", 413 drop ? "DROP: " : "", ftype, sbuf_data(sb)); 414 sbuf_delete(sb); 415 #endif 416 417 error = drop ? 0 : 418 l9p_pufcall(&req->lr_resp_msg, &req->lr_resp, conn->lc_version); 419 if (rmtag) 420 ht_remove(&conn->lc_requests, req->lr_req.hdr.tag); 421 if (error != 0) { 422 L9P_LOG(L9P_ERROR, "cannot pack response"); 423 drop = true; 424 } 425 426 if (drop) { 427 conn->lc_lt.lt_drop_response(req, 428 req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov, 429 conn->lc_lt.lt_aux); 430 } else { 431 iosize = req->lr_resp_msg.lm_size; 432 433 /* 434 * Include I/O size in calculation for Rread and 435 * Rreaddir responses. 436 */ 437 if (req->lr_resp.hdr.type == L9P_RREAD || 438 req->lr_resp.hdr.type == L9P_RREADDIR) 439 iosize += req->lr_resp.io.count; 440 441 conn->lc_lt.lt_send_response(req, 442 req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov, 443 iosize, conn->lc_lt.lt_aux); 444 } 445 446 l9p_freefcall(&req->lr_req); 447 l9p_freefcall(&req->lr_resp); 448 449 free(req); 450 } 451 452 /* 453 * This allows a caller to iterate through the data in a 454 * read or write request (creating the data if packing, 455 * scanning through it if unpacking). This is used for 456 * writing readdir entries, so mode should be L9P_PACK 457 * (but we allow L9P_UNPACK so that debug code can also scan 458 * through the data later, if desired). 459 * 460 * This relies on the Tread op having positioned the request's 461 * iov to the beginning of the data buffer (note the l9p_seek_iov 462 * in l9p_dispatch_tread). 463 */ 464 void 465 l9p_init_msg(struct l9p_message *msg, struct l9p_request *req, 466 enum l9p_pack_mode mode) 467 { 468 469 msg->lm_size = 0; 470 msg->lm_mode = mode; 471 msg->lm_cursor_iov = 0; 472 msg->lm_cursor_offset = 0; 473 msg->lm_niov = req->lr_data_niov; 474 memcpy(msg->lm_iov, req->lr_data_iov, 475 sizeof (struct iovec) * req->lr_data_niov); 476 } 477 478 enum fid_lookup_flags { 479 F_REQUIRE_OPEN = 0x01, /* require that the file be marked OPEN */ 480 F_REQUIRE_DIR = 0x02, /* require that the file be marked ISDIR */ 481 F_REQUIRE_XATTR = 0x04, /* require that the file be marked XATTR */ 482 F_REQUIRE_AUTH = 0x08, /* require that the fid be marked AUTH */ 483 F_FORBID_OPEN = 0x10, /* forbid that the file be marked OPEN */ 484 F_FORBID_DIR = 0x20, /* forbid that the file be marked ISDIR */ 485 F_FORBID_XATTR = 0x40, /* forbid that the file be marked XATTR */ 486 F_ALLOW_AUTH = 0x80, /* allow that the fid be marked AUTH */ 487 }; 488 489 /* 490 * Look up a fid. It must correspond to a valid file, else we return 491 * the given errno (some "not a valid fid" calls must return EIO and 492 * some must return EINVAL and qemu returns ENOENT in other cases and 493 * so on, so we just provide a general "return this error number"). 494 * 495 * Callers may also set constraints: fid must be (or not be) open, 496 * must be (or not be) a directory, must be (or not be) an xattr. 497 * 498 * Only one op has a fid that *must* be an auth fid. Most ops forbid 499 * auth fids So instead of FORBID we have ALLOW here and the default 500 * is FORBID. 501 */ 502 static inline int 503 fid_lookup(struct l9p_connection *conn, uint32_t fid, int err, int flags, 504 struct l9p_fid **afile) 505 { 506 struct l9p_fid *file; 507 508 file = ht_find(&conn->lc_files, fid); 509 if (file == NULL) 510 return (err); 511 512 /* 513 * As soon as we go multithreaded / async, this 514 * assert has to become "return EINVAL" or "return err". 515 * 516 * We may also need a way to mark a fid as 517 * "in async op" (valid for some purposes, but cannot be 518 * used elsewhere until async op is completed or aborted). 519 * 520 * For now, this serves for bug-detecting. 521 */ 522 assert(l9p_fid_isvalid(file)); 523 524 /* 525 * Note that we're inline expanded and flags is constant, 526 * so unnecessary tests just drop out entirely. 527 */ 528 if ((flags & F_REQUIRE_OPEN) && !l9p_fid_isopen(file)) 529 return (EINVAL); 530 if ((flags & F_FORBID_OPEN) && l9p_fid_isopen(file)) 531 return (EINVAL); 532 if ((flags & F_REQUIRE_DIR) && !l9p_fid_isdir(file)) 533 return (ENOTDIR); 534 if ((flags & F_FORBID_DIR) && l9p_fid_isdir(file)) 535 return (EISDIR); 536 if ((flags & F_REQUIRE_XATTR) && !l9p_fid_isxattr(file)) 537 return (EINVAL); 538 if ((flags & F_FORBID_XATTR) && l9p_fid_isxattr(file)) 539 return (EINVAL); 540 if (l9p_fid_isauth(file)) { 541 if ((flags & (F_REQUIRE_AUTH | F_ALLOW_AUTH)) == 0) 542 return (EINVAL); 543 } else if (flags & F_REQUIRE_AUTH) 544 return (EINVAL); 545 *afile = file; 546 return (0); 547 } 548 549 /* 550 * Append variable-size stat object and adjust io count. 551 * Returns 0 if the entire stat object was packed, -1 if not. 552 * A fully packed object updates the request's io count. 553 * 554 * Caller must use their own private l9p_message object since 555 * a partially packed object will leave the message object in 556 * a useless state. 557 * 558 * Frees the stat object. 559 */ 560 int 561 l9p_pack_stat(struct l9p_message *msg, struct l9p_request *req, 562 struct l9p_stat *st) 563 { 564 struct l9p_connection *conn = req->lr_conn; 565 uint16_t size = l9p_sizeof_stat(st, conn->lc_version); 566 int ret = 0; 567 568 assert(msg->lm_mode == L9P_PACK); 569 570 if (req->lr_resp.io.count + size > req->lr_req.io.count || 571 l9p_pustat(msg, st, conn->lc_version) < 0) 572 ret = -1; 573 else 574 req->lr_resp.io.count += size; 575 l9p_freestat(st); 576 return (ret); 577 } 578 579 static int 580 l9p_dispatch_tversion(struct l9p_request *req) 581 { 582 struct l9p_connection *conn = req->lr_conn; 583 struct l9p_server *server = conn->lc_server; 584 enum l9p_version remote_version = L9P_INVALID_VERSION; 585 size_t i; 586 const char *remote_version_name; 587 588 for (i = 0; i < N(l9p_versions); i++) { 589 if (strcmp(req->lr_req.version.version, 590 l9p_versions[i].name) == 0) { 591 remote_version = (enum l9p_version)i; 592 break; 593 } 594 } 595 596 if (remote_version == L9P_INVALID_VERSION) { 597 L9P_LOG(L9P_ERROR, "unsupported remote version: %s", 598 req->lr_req.version.version); 599 return (ENOSYS); 600 } 601 602 remote_version_name = l9p_versions[remote_version].name; 603 L9P_LOG(L9P_INFO, "remote version: %s", remote_version_name); 604 L9P_LOG(L9P_INFO, "local version: %s", 605 l9p_versions[server->ls_max_version].name); 606 607 conn->lc_version = MIN(remote_version, server->ls_max_version); 608 conn->lc_msize = MIN(req->lr_req.version.msize, conn->lc_msize); 609 conn->lc_max_io_size = conn->lc_msize - 24; 610 req->lr_resp.version.version = strdup(remote_version_name); 611 req->lr_resp.version.msize = conn->lc_msize; 612 return (0); 613 } 614 615 static int 616 l9p_dispatch_tattach(struct l9p_request *req) 617 { 618 struct l9p_connection *conn = req->lr_conn; 619 struct l9p_backend *be; 620 struct l9p_fid *fid; 621 int error; 622 623 /* 624 * We still don't have Tauth yet, but let's code this part 625 * anyway. 626 * 627 * Look up the auth fid first since if it fails we can just 628 * return immediately. 629 */ 630 if (req->lr_req.tattach.afid != L9P_NOFID) { 631 error = fid_lookup(conn, req->lr_req.tattach.afid, EINVAL, 632 F_REQUIRE_AUTH, &req->lr_fid2); 633 if (error) 634 return (error); 635 } else 636 req->lr_fid2 = NULL; 637 638 fid = l9p_connection_alloc_fid(conn, req->lr_req.hdr.fid); 639 if (fid == NULL) 640 return (EINVAL); 641 642 be = conn->lc_server->ls_backend; 643 644 req->lr_fid = fid; 645 646 /* For backend convenience, set NONUNAME on 9P2000. */ 647 if (conn->lc_version == L9P_2000) 648 req->lr_req.tattach.n_uname = L9P_NONUNAME; 649 error = be->attach(be->softc, req); 650 651 /* 652 * On success, fid becomes valid; on failure, disconnect. 653 * It certainly *should* be a directory here... 654 */ 655 if (error == 0) { 656 l9p_fid_setvalid(fid); 657 if (req->lr_resp.rattach.qid.type & L9P_QTDIR) 658 l9p_fid_setdir(fid); 659 } else 660 l9p_connection_remove_fid(conn, fid); 661 return (error); 662 } 663 664 static int 665 l9p_dispatch_tclunk(struct l9p_request *req) 666 { 667 struct l9p_connection *conn = req->lr_conn; 668 struct l9p_backend *be; 669 struct l9p_fid *fid; 670 int error; 671 672 /* Note that clunk is the only way to dispose of an auth fid. */ 673 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 674 F_ALLOW_AUTH, &fid); 675 if (error) 676 return (error); 677 678 be = conn->lc_server->ls_backend; 679 l9p_fid_unsetvalid(fid); 680 681 /* 682 * If it's an xattr fid there must, by definition, be an 683 * xattrclunk. The xattrclunk function can only be NULL if 684 * xattrwalk and xattrcreate are NULL or always return error. 685 * 686 * Q: do we want to allow async xattrclunk in case of very 687 * large xattr create? This will make things difficult, 688 * so probably not. 689 */ 690 if (l9p_fid_isxattr(fid)) 691 error = be->xattrclunk(be->softc, fid); 692 else 693 error = be->clunk(be->softc, fid); 694 695 /* fid is now gone regardless of any error return */ 696 l9p_connection_remove_fid(conn, fid); 697 return (error); 698 } 699 700 static int 701 l9p_dispatch_tcreate(struct l9p_request *req) 702 { 703 struct l9p_connection *conn = req->lr_conn; 704 struct l9p_backend *be; 705 uint32_t dmperm; 706 int error; 707 708 /* Incoming fid must represent a directory that has not been opened. */ 709 error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 710 F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid); 711 if (error) 712 return (error); 713 714 be = conn->lc_server->ls_backend; 715 dmperm = req->lr_req.tcreate.perm; 716 #define MKDIR_OR_SIMILAR \ 717 (L9P_DMDIR | L9P_DMSYMLINK | L9P_DMNAMEDPIPE | L9P_DMSOCKET | L9P_DMDEVICE) 718 719 /* 720 * TODO: 721 * - check new file name 722 * - break out different kinds of create (file vs mkdir etc) 723 * - add async file-create (leaves req->lr_fid in limbo) 724 * 725 * A successful file-create changes the fid into an open file. 726 */ 727 error = be->create(be->softc, req); 728 if (error == 0 && (dmperm & MKDIR_OR_SIMILAR) == 0) { 729 l9p_fid_unsetdir(req->lr_fid); 730 l9p_fid_setopen(req->lr_fid); 731 } 732 733 return (error); 734 } 735 736 static int 737 l9p_dispatch_topen(struct l9p_request *req) 738 { 739 struct l9p_connection *conn = req->lr_conn; 740 struct l9p_backend *be; 741 int error; 742 743 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 744 F_FORBID_OPEN | F_FORBID_XATTR, &req->lr_fid); 745 if (error) 746 return (error); 747 748 be = conn->lc_server->ls_backend; 749 750 /* 751 * TODO: 752 * - add async open (leaves req->lr_fid in limbo) 753 */ 754 error = be->open(be->softc, req); 755 if (error == 0) 756 l9p_fid_setopen(req->lr_fid); 757 return (error); 758 } 759 760 static int 761 l9p_dispatch_tread(struct l9p_request *req) 762 { 763 struct l9p_connection *conn = req->lr_conn; 764 struct l9p_backend *be; 765 struct l9p_fid *fid; 766 int error; 767 768 /* Xattr fids are not open, so we need our own tests. */ 769 error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 0, &req->lr_fid); 770 if (error) 771 return (error); 772 773 /* 774 * Adjust so that writing messages (packing data) starts 775 * right after the count field in the response. 776 * 777 * size[4] + Rread[1] + tag[2] + count[4] = 11 778 */ 779 l9p_seek_iov(req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov, 780 req->lr_data_iov, &req->lr_data_niov, 11); 781 782 /* 783 * If it's an xattr fid there must, by definition, be an 784 * xattrread. The xattrread function can only be NULL if 785 * xattrwalk and xattrcreate are NULL or always return error. 786 * 787 * TODO: 788 * separate out directory-read 789 * allow async read 790 */ 791 be = conn->lc_server->ls_backend; 792 fid = req->lr_fid; 793 if (l9p_fid_isxattr(fid)) { 794 error = be->xattrread(be->softc, req); 795 } else if (l9p_fid_isopen(fid)) { 796 error = be->read(be->softc, req); 797 } else { 798 error = EINVAL; 799 } 800 801 return (error); 802 } 803 804 static int 805 l9p_dispatch_tremove(struct l9p_request *req) 806 { 807 struct l9p_connection *conn = req->lr_conn; 808 struct l9p_backend *be; 809 struct l9p_fid *fid; 810 int error; 811 812 /* 813 * ?? Should we allow Tremove on auth fids? If so, do 814 * we pretend it is just a Tclunk? 815 */ 816 error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 0, &fid); 817 if (error) 818 return (error); 819 820 be = conn->lc_server->ls_backend; 821 l9p_fid_unsetvalid(fid); 822 823 error = be->remove(be->softc, fid); 824 /* fid is now gone regardless of any error return */ 825 l9p_connection_remove_fid(conn, fid); 826 return (error); 827 } 828 829 static int 830 l9p_dispatch_tstat(struct l9p_request *req) 831 { 832 struct l9p_connection *conn = req->lr_conn; 833 struct l9p_backend *be; 834 struct l9p_fid *fid; 835 int error; 836 837 /* Allow Tstat on auth fid? Seems harmless enough... */ 838 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 839 F_ALLOW_AUTH, &fid); 840 if (error) 841 return (error); 842 843 be = conn->lc_server->ls_backend; 844 req->lr_fid = fid; 845 error = be->stat(be->softc, req); 846 847 if (error == 0) { 848 if (l9p_fid_isauth(fid)) 849 req->lr_resp.rstat.stat.qid.type |= L9P_QTAUTH; 850 851 /* should we check req->lr_resp.rstat.qid.type L9P_QTDIR bit? */ 852 if (req->lr_resp.rstat.stat.qid.type &= L9P_QTDIR) 853 l9p_fid_setdir(fid); 854 else 855 l9p_fid_unsetdir(fid); 856 } 857 858 return (error); 859 } 860 861 static int 862 l9p_dispatch_twalk(struct l9p_request *req) 863 { 864 struct l9p_connection *conn = req->lr_conn; 865 struct l9p_backend *be; 866 struct l9p_fid *fid, *newfid; 867 uint16_t n; 868 int error; 869 870 /* Can forbid XATTR, but cannot require DIR. */ 871 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 872 F_FORBID_XATTR, &fid); 873 if (error) 874 return (error); 875 876 if (req->lr_req.twalk.hdr.fid != req->lr_req.twalk.newfid) { 877 newfid = l9p_connection_alloc_fid(conn, 878 req->lr_req.twalk.newfid); 879 if (newfid == NULL) 880 return (EINVAL); 881 } else 882 newfid = fid; 883 884 be = conn->lc_server->ls_backend; 885 req->lr_fid = fid; 886 req->lr_newfid = newfid; 887 error = be->walk(be->softc, req); 888 889 /* 890 * If newfid == fid, then fid itself has (potentially) changed, 891 * but is still valid. Otherwise set newfid valid on 892 * success, and destroy it on error. 893 */ 894 if (newfid != fid) { 895 if (error == 0) 896 l9p_fid_setvalid(newfid); 897 else 898 l9p_connection_remove_fid(conn, newfid); 899 } 900 901 /* 902 * If we walked any name elements, the last (n-1'th) qid 903 * has the type (dir vs file) for the new fid. Otherwise 904 * the type of newfid is the same as fid. Of course, if 905 * n==0 and fid==newfid, fid is already set up correctly 906 * as the whole thing was a big no-op, but it's safe to 907 * copy its dir bit to itself. 908 */ 909 if (error == 0) { 910 n = req->lr_resp.rwalk.nwqid; 911 if (n > 0) { 912 if (req->lr_resp.rwalk.wqid[n - 1].type & L9P_QTDIR) 913 l9p_fid_setdir(newfid); 914 } else { 915 if (l9p_fid_isdir(fid)) 916 l9p_fid_setdir(newfid); 917 } 918 } 919 return (error); 920 } 921 922 static int 923 l9p_dispatch_twrite(struct l9p_request *req) 924 { 925 struct l9p_connection *conn = req->lr_conn; 926 struct l9p_backend *be; 927 struct l9p_fid *fid; 928 int error; 929 930 /* Cannot require open due to xattr write, but can forbid dir. */ 931 error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 932 F_FORBID_DIR, &req->lr_fid); 933 if (error) 934 return (error); 935 936 /* 937 * Adjust to point to the data to be written (a la 938 * l9p_dispatch_tread, but we're pointing into the request 939 * buffer rather than the response): 940 * 941 * size[4] + Twrite[1] + tag[2] + fid[4] + offset[8] + count[4] = 23 942 */ 943 l9p_seek_iov(req->lr_req_msg.lm_iov, req->lr_req_msg.lm_niov, 944 req->lr_data_iov, &req->lr_data_niov, 23); 945 946 /* 947 * Unlike read, write and xattrwrite are optional (for R/O fs). 948 * 949 * TODO: 950 * allow async write 951 */ 952 be = conn->lc_server->ls_backend; 953 fid = req->lr_fid; 954 if (l9p_fid_isxattr(fid)) { 955 error = be->xattrwrite != NULL ? 956 be->xattrwrite(be->softc, req) : ENOSYS; 957 } else if (l9p_fid_isopen(fid)) { 958 error = be->write != NULL ? 959 be->write(be->softc, req) : ENOSYS; 960 } else { 961 error = EINVAL; 962 } 963 964 return (error); 965 } 966 967 static int 968 l9p_dispatch_twstat(struct l9p_request *req) 969 { 970 struct l9p_connection *conn = req->lr_conn; 971 struct l9p_backend *be; 972 int error; 973 974 error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 975 F_FORBID_XATTR, &req->lr_fid); 976 if (error) 977 return (error); 978 979 be = conn->lc_server->ls_backend; 980 error = be->wstat != NULL ? be->wstat(be->softc, req) : ENOSYS; 981 return (error); 982 } 983 984 static int 985 l9p_dispatch_tstatfs(struct l9p_request *req) 986 { 987 struct l9p_connection *conn = req->lr_conn; 988 struct l9p_backend *be; 989 int error; 990 991 /* Should we allow statfs on auth fids? */ 992 error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 0, &req->lr_fid); 993 if (error) 994 return (error); 995 996 be = conn->lc_server->ls_backend; 997 error = be->statfs(be->softc, req); 998 return (error); 999 } 1000 1001 static int 1002 l9p_dispatch_tlopen(struct l9p_request *req) 1003 { 1004 struct l9p_connection *conn = req->lr_conn; 1005 struct l9p_backend *be; 1006 int error; 1007 1008 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1009 F_FORBID_OPEN | F_FORBID_XATTR, &req->lr_fid); 1010 if (error) 1011 return (error); 1012 1013 be = conn->lc_server->ls_backend; 1014 1015 /* 1016 * TODO: 1017 * - add async open (leaves req->lr_fid in limbo) 1018 */ 1019 error = be->lopen != NULL ? be->lopen(be->softc, req) : ENOSYS; 1020 if (error == 0) 1021 l9p_fid_setopen(req->lr_fid); 1022 return (error); 1023 } 1024 1025 static int 1026 l9p_dispatch_tlcreate(struct l9p_request *req) 1027 { 1028 struct l9p_connection *conn = req->lr_conn; 1029 struct l9p_backend *be; 1030 int error; 1031 1032 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1033 F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid); 1034 if (error) 1035 return (error); 1036 1037 be = conn->lc_server->ls_backend; 1038 1039 /* 1040 * TODO: 1041 * - check new file name 1042 * - add async create (leaves req->lr_fid in limbo) 1043 */ 1044 error = be->lcreate != NULL ? be->lcreate(be->softc, req) : ENOSYS; 1045 if (error == 0) { 1046 l9p_fid_unsetdir(req->lr_fid); 1047 l9p_fid_setopen(req->lr_fid); 1048 } 1049 return (error); 1050 } 1051 1052 static int 1053 l9p_dispatch_tsymlink(struct l9p_request *req) 1054 { 1055 struct l9p_connection *conn = req->lr_conn; 1056 struct l9p_backend *be; 1057 int error; 1058 1059 /* This doesn't affect the containing dir; maybe allow OPEN? */ 1060 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1061 F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid); 1062 if (error) 1063 return (error); 1064 1065 be = conn->lc_server->ls_backend; 1066 1067 /* 1068 * TODO: 1069 * - check new file name 1070 */ 1071 error = be->symlink != NULL ? be->symlink(be->softc, req) : ENOSYS; 1072 return (error); 1073 } 1074 1075 static int 1076 l9p_dispatch_tmknod(struct l9p_request *req) 1077 { 1078 struct l9p_connection *conn = req->lr_conn; 1079 struct l9p_backend *be; 1080 int error; 1081 1082 /* This doesn't affect the containing dir; maybe allow OPEN? */ 1083 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1084 F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid); 1085 if (error) 1086 return (error); 1087 1088 be = conn->lc_server->ls_backend; 1089 1090 /* 1091 * TODO: 1092 * - check new file name 1093 */ 1094 error = be->mknod != NULL ? be->mknod(be->softc, req) : ENOSYS; 1095 return (error); 1096 } 1097 1098 static int 1099 l9p_dispatch_trename(struct l9p_request *req) 1100 { 1101 struct l9p_connection *conn = req->lr_conn; 1102 struct l9p_backend *be; 1103 int error; 1104 1105 /* Rename directory or file (including symlink etc). */ 1106 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1107 F_FORBID_XATTR, &req->lr_fid); 1108 if (error) 1109 return (error); 1110 1111 /* Doesn't affect new dir fid; maybe allow OPEN? */ 1112 error = fid_lookup(conn, req->lr_req.trename.dfid, ENOENT, 1113 F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid2); 1114 if (error) 1115 return (error); 1116 1117 be = conn->lc_server->ls_backend; 1118 1119 /* 1120 * TODO: 1121 * - check new file name (trename.name) 1122 */ 1123 error = be->rename != NULL ? be->rename(be->softc, req) : ENOSYS; 1124 return (error); 1125 } 1126 1127 static int 1128 l9p_dispatch_treadlink(struct l9p_request *req) 1129 { 1130 struct l9p_connection *conn = req->lr_conn; 1131 struct l9p_backend *be; 1132 int error; 1133 1134 /* 1135 * The underlying readlink will fail unless it's a symlink, 1136 * and the back end has to check, but we might as well forbid 1137 * directories and open files here since it's cheap. 1138 */ 1139 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1140 F_FORBID_DIR | F_FORBID_OPEN, &req->lr_fid); 1141 if (error) 1142 return (error); 1143 1144 be = conn->lc_server->ls_backend; 1145 1146 error = be->readlink != NULL ? be->readlink(be->softc, req) : ENOSYS; 1147 return (error); 1148 } 1149 1150 static int 1151 l9p_dispatch_tgetattr(struct l9p_request *req) 1152 { 1153 struct l9p_connection *conn = req->lr_conn; 1154 struct l9p_backend *be; 1155 int error; 1156 1157 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1158 F_FORBID_XATTR, &req->lr_fid); 1159 if (error) 1160 return (error); 1161 1162 be = conn->lc_server->ls_backend; 1163 1164 error = be->getattr != NULL ? be->getattr(be->softc, req) : ENOSYS; 1165 return (error); 1166 } 1167 1168 static int 1169 l9p_dispatch_tsetattr(struct l9p_request *req) 1170 { 1171 struct l9p_connection *conn = req->lr_conn; 1172 struct l9p_backend *be; 1173 int error; 1174 1175 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1176 F_FORBID_XATTR, &req->lr_fid); 1177 if (error) 1178 return (error); 1179 1180 be = conn->lc_server->ls_backend; 1181 1182 error = be->setattr != NULL ? be->setattr(be->softc, req) : ENOSYS; 1183 return (error); 1184 } 1185 1186 static int 1187 l9p_dispatch_txattrwalk(struct l9p_request *req) 1188 { 1189 struct l9p_connection *conn = req->lr_conn; 1190 struct l9p_backend *be; 1191 struct l9p_fid *fid, *newfid; 1192 int error; 1193 1194 /* 1195 * Not sure if we care if file-or-dir is open or not. 1196 * However, the fid argument should always be a file or 1197 * dir and the newfid argument must be supplied, must 1198 * be different, and always becomes a new xattr, 1199 * so this is not very much like Twalk. 1200 */ 1201 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1202 F_FORBID_XATTR, &fid); 1203 if (error) 1204 return (error); 1205 1206 newfid = l9p_connection_alloc_fid(conn, req->lr_req.txattrwalk.newfid); 1207 if (newfid == NULL) 1208 return (EINVAL); 1209 1210 be = conn->lc_server->ls_backend; 1211 1212 req->lr_fid = fid; 1213 req->lr_newfid = newfid; 1214 error = be->xattrwalk != NULL ? be->xattrwalk(be->softc, req) : ENOSYS; 1215 1216 /* 1217 * Success/fail is similar to Twalk, except that we need 1218 * to set the xattr type bit in the new fid. It's also 1219 * much simpler since newfid is always a new fid. 1220 */ 1221 if (error == 0) { 1222 l9p_fid_setvalid(newfid); 1223 l9p_fid_setxattr(newfid); 1224 } else { 1225 l9p_connection_remove_fid(conn, newfid); 1226 } 1227 return (error); 1228 } 1229 1230 static int 1231 l9p_dispatch_txattrcreate(struct l9p_request *req) 1232 { 1233 struct l9p_connection *conn = req->lr_conn; 1234 struct l9p_backend *be; 1235 struct l9p_fid *fid; 1236 int error; 1237 1238 /* 1239 * Forbid incoming open fid since it's going to become an 1240 * xattr fid instead. If it turns out we need to allow 1241 * it, fs code will need to handle this. 1242 * 1243 * Curiously, qemu 9pfs uses ENOENT for a bad txattrwalk 1244 * fid, but EINVAL for txattrcreate (so we do too). 1245 */ 1246 error = fid_lookup(conn, req->lr_req.hdr.fid, EINVAL, 1247 F_FORBID_XATTR | F_FORBID_OPEN, &fid); 1248 if (error) 1249 return (error); 1250 1251 be = conn->lc_server->ls_backend; 1252 1253 req->lr_fid = fid; 1254 error = be->xattrcreate != NULL ? be->xattrcreate(be->softc, req) : 1255 ENOSYS; 1256 1257 /* 1258 * On success, fid has changed from a regular (file or dir) 1259 * fid to an xattr fid. 1260 */ 1261 if (error == 0) { 1262 l9p_fid_unsetdir(fid); 1263 l9p_fid_setxattr(fid); 1264 } 1265 return (error); 1266 } 1267 1268 static int 1269 l9p_dispatch_treaddir(struct l9p_request *req) 1270 { 1271 struct l9p_connection *conn = req->lr_conn; 1272 struct l9p_backend *be; 1273 int error; 1274 1275 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1276 F_REQUIRE_DIR | F_REQUIRE_OPEN, &req->lr_fid); 1277 if (error) 1278 return (error); 1279 1280 /* 1281 * Adjust so that writing messages (packing data) starts 1282 * right after the count field in the response. 1283 * 1284 * size[4] + Rreaddir[1] + tag[2] + count[4] = 11 1285 */ 1286 l9p_seek_iov(req->lr_resp_msg.lm_iov, req->lr_resp_msg.lm_niov, 1287 req->lr_data_iov, &req->lr_data_niov, 11); 1288 1289 be = conn->lc_server->ls_backend; 1290 1291 error = be->readdir != NULL ? be->readdir(be->softc, req) : ENOSYS; 1292 return (error); 1293 } 1294 1295 static int 1296 l9p_dispatch_tfsync(struct l9p_request *req) 1297 { 1298 struct l9p_connection *conn = req->lr_conn; 1299 struct l9p_backend *be; 1300 int error; 1301 1302 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1303 F_REQUIRE_OPEN, &req->lr_fid); 1304 if (error) 1305 return (error); 1306 1307 be = conn->lc_server->ls_backend; 1308 1309 error = be->fsync != NULL ? be->fsync(be->softc, req) : ENOSYS; 1310 return (error); 1311 } 1312 1313 static int 1314 l9p_dispatch_tlock(struct l9p_request *req) 1315 { 1316 struct l9p_connection *conn = req->lr_conn; 1317 struct l9p_backend *be; 1318 int error; 1319 1320 /* Forbid directories? */ 1321 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1322 F_REQUIRE_OPEN, &req->lr_fid); 1323 if (error) 1324 return (error); 1325 1326 be = conn->lc_server->ls_backend; 1327 1328 /* 1329 * TODO: multiple client handling; perhaps async locking. 1330 */ 1331 error = be->lock != NULL ? be->lock(be->softc, req) : ENOSYS; 1332 return (error); 1333 } 1334 1335 static int 1336 l9p_dispatch_tgetlock(struct l9p_request *req) 1337 { 1338 struct l9p_connection *conn = req->lr_conn; 1339 struct l9p_backend *be; 1340 int error; 1341 1342 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1343 F_REQUIRE_OPEN, &req->lr_fid); 1344 if (error) 1345 return (error); 1346 1347 be = conn->lc_server->ls_backend; 1348 1349 /* 1350 * TODO: multiple client handling; perhaps async locking. 1351 */ 1352 error = be->getlock != NULL ? be->getlock(be->softc, req) : ENOSYS; 1353 return (error); 1354 } 1355 1356 static int 1357 l9p_dispatch_tlink(struct l9p_request *req) 1358 { 1359 struct l9p_connection *conn = req->lr_conn; 1360 struct l9p_backend *be; 1361 int error; 1362 1363 /* 1364 * Note, dfid goes into fid2 in current scheme. 1365 * 1366 * Allow open dir? Target dir fid is not modified... 1367 */ 1368 error = fid_lookup(conn, req->lr_req.tlink.dfid, ENOENT, 1369 F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid2); 1370 if (error) 1371 return (error); 1372 1373 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1374 F_FORBID_DIR | F_FORBID_XATTR, &req->lr_fid); 1375 if (error) 1376 return (error); 1377 1378 be = conn->lc_server->ls_backend; 1379 1380 error = be->link != NULL ? be->link(be->softc, req) : ENOSYS; 1381 return (error); 1382 } 1383 1384 static int 1385 l9p_dispatch_tmkdir(struct l9p_request *req) 1386 { 1387 struct l9p_connection *conn = req->lr_conn; 1388 struct l9p_backend *be; 1389 int error; 1390 1391 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1392 F_REQUIRE_DIR | F_FORBID_OPEN, &req->lr_fid); 1393 if (error) 1394 return (error); 1395 1396 /* Slashes embedded in the name are not allowed */ 1397 if (strchr(req->lr_req.tlcreate.name, '/') != NULL) 1398 return (EINVAL); 1399 1400 be = conn->lc_server->ls_backend; 1401 error = be->mkdir != NULL ? be->mkdir(be->softc, req) : ENOSYS; 1402 return (error); 1403 } 1404 1405 static int 1406 l9p_dispatch_trenameat(struct l9p_request *req) 1407 { 1408 struct l9p_connection *conn = req->lr_conn; 1409 struct l9p_backend *be; 1410 int error; 1411 1412 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1413 F_REQUIRE_DIR, &req->lr_fid); 1414 if (error) 1415 return (error); 1416 1417 error = fid_lookup(conn, req->lr_req.trenameat.newdirfid, ENOENT, 1418 F_REQUIRE_DIR, &req->lr_fid2); 1419 if (error) 1420 return (error); 1421 1422 be = conn->lc_server->ls_backend; 1423 1424 /* TODO: check old and new names */ 1425 error = be->renameat != NULL ? be->renameat(be->softc, req) : ENOSYS; 1426 return (error); 1427 } 1428 1429 static int 1430 l9p_dispatch_tunlinkat(struct l9p_request *req) 1431 { 1432 struct l9p_connection *conn = req->lr_conn; 1433 struct l9p_backend *be; 1434 int error; 1435 1436 error = fid_lookup(conn, req->lr_req.hdr.fid, ENOENT, 1437 F_REQUIRE_DIR, &req->lr_fid); 1438 if (error) 1439 return (error); 1440 1441 be = conn->lc_server->ls_backend; 1442 1443 /* TODO: check dir-or-file name */ 1444 error = be->unlinkat != NULL ? be->unlinkat(be->softc, req) : ENOSYS; 1445 return (error); 1446 } 1447