commit 8f9f99f7fc753a3bf04eff946db4332ebd75a811 from: Omar Polo date: Sun Jan 16 11:08:21 2022 UTC rework walk_path In particular it's important not to die if the first component can't be walked for any reason! commit - b2263c45b76e09cf07b7149fb84b85777c682047 commit + 8f9f99f7fc753a3bf04eff946db4332ebd75a811 blob - 39f6ae2ca4f588e5ce2850fb6cf4fdf72c05cf47 blob + a2b0e5c0e7c1396d99b63d21105dcba6e63fbe42 --- kamiftp/ftp.c +++ kamiftp/ftp.c @@ -381,6 +381,27 @@ expect2(uint8_t type, uint16_t tag) errx(1, "expected tag 0x%x, got 0x%x", tag, t); } +static char * +check(uint8_t type, uint16_t tag) +{ + uint16_t rtag; + uint8_t rtype; + + rtype = np_read8(buf); + rtag = np_read16(buf); + if (rtype == type) { + if (rtag != tag) + errx(1, "expected tag 0x%x, got 0x%x", tag, rtag); + return NULL; + } + + if (rtype == Rerror) + return np_readstr(buf); + + errx(1, "expected %s, got msg type %s", + pp_msg_type(type), pp_msg_type(rtype)); +} + static void do_version(void) { @@ -469,10 +490,11 @@ dup_fid(int fid, int nfid) ASSERT_EMPTYBUF(); } -static int -walk_path(int fid, int newfid, const char *path, struct qid *qid) +static char * +walk_path(int fid, int newfid, const char *path, int *missing, + struct qid *qid) { - char *wnames[MAXWELEM], *p, *t; + char *wnames[MAXWELEM], *p, *t, *errstr; size_t nwname, i; uint16_t nwqid; @@ -493,8 +515,11 @@ walk_path(int fid, int newfid, const char *path, struc twalk(fid, newfid, (const char **)wnames, nwname); do_send(); recv_msg(); - expect2(Rwalk, iota_tag); + *missing = nwname; + if ((errstr = check(Rwalk, iota_tag)) != NULL) + return errstr; + nwqid = np_read16(buf); assert(nwqid <= nwname); @@ -504,7 +529,8 @@ walk_path(int fid, int newfid, const char *path, struc free(p); - return nwqid == nwname; + *missing = nwname - nwqid; + return NULL; } static void @@ -770,7 +796,8 @@ static void cmd_cd(int argc, const char **argv) { struct qid qid; - int nfid; + int nfid, miss; + char *errstr; if (argc != 1) { printf("usage: cd remote-path\n"); @@ -778,14 +805,21 @@ cmd_cd(int argc, const char **argv) } nfid = pwdfid+1; - if (walk_path(pwdfid, nfid, argv[0], &qid) == -1 || - !(qid.type & QTDIR)) { - printf("can't cd %s\n", argv[0]); + errstr = walk_path(pwdfid, nfid, argv[0], &miss, &qid); + if (errstr != NULL) { + printf("%s: %s\n", argv[0], errstr); + free(errstr); + return; + } + + if (miss != 0 || !(qid.type & QTDIR)) { + printf("%s: not a directory\n", argv[0]); do_clunk(nfid); - } else { - do_clunk(pwdfid); - pwdfid = nfid; + return; } + + do_clunk(pwdfid); + pwdfid = nfid; } static void @@ -793,8 +827,8 @@ cmd_get(int argc, const char **argv) { struct qid qid; const char *l; - int nfid; - int fd; + char *errstr; + int nfid, fd, miss; if (argc != 1 && argc != 2) { printf("usage: get remote-file [local-file]\n"); @@ -809,13 +843,15 @@ cmd_get(int argc, const char **argv) l = argv[0]; nfid = pwdfid+1; - if (walk_path(pwdfid, nfid, argv[0], &qid) == -1) { - printf("can't fetch %s\n", argv[0]); + errstr = walk_path(pwdfid, nfid, argv[0], &miss, &qid); + if (errstr != NULL) { + printf("%s: %s\n", argv[0], errstr); + free(errstr); return; } - if (qid.type != 0) { - printf("can't fetch %s\n", argv[0]); + if (miss != 0 || qid.type != 0) { + printf("%s: not a file\n", argv[0]); do_clunk(nfid); return; } @@ -921,8 +957,8 @@ static void cmd_page(int argc, const char **argv) { struct qid qid; - int nfid, tmpfd; - char sfn[24], p[PATH_MAX], *name; + int nfid, tmpfd, miss; + char sfn[24], p[PATH_MAX], *name, *errstr; if (argc != 1) { puts("usage: page file"); @@ -930,13 +966,15 @@ cmd_page(int argc, const char **argv) } nfid = pwdfid+1; - if (walk_path(pwdfid, nfid, *argv, &qid) == -1) { - printf("can't fetch %s\n", *argv); + errstr = walk_path(pwdfid, nfid, *argv, &miss, &qid); + if (errstr != NULL) { + printf("%s: %s\n", *argv, errstr); + free(errstr); return; } - if (qid.type != 0) { - printf("can't page file type %s\n", pp_qid_type(qid.type)); + if (miss != 0 || qid.type != 0) { + printf("%s: not a file\n", *argv); do_clunk(nfid); return; }