commit f4f42cd328771f335ec1dc15884f2bf337bdf36a from: Omar Polo date: Sun Jan 09 09:39:22 2022 UTC fix cd Walk can be successful in various conditions where cd has to fail. For instance, we may have reached a file or we couldn't walk all the required components. In these "soft-fail" cases, the walk has mutated the fids, so to abort the cd we have to do a walk using a second fid and then clunk the old or new one depending on if it was _completely_ successful or not. Another option may be to track the number of walked path and attempt to walk '..' the right amount of times, this would saves a Tclunk in the case the walk succeeded and require a slightly bigger 9P packet to be sent in the failure case. It would complicate the walk_path API though, so I've not chosen this option. commit - 63b9781e99a5b7519106753eb93d50fb568d4d4c commit + f4f42cd328771f335ec1dc15884f2bf337bdf36a blob - 00de21321efa7a139f236cbb2e24eb7ee0ee00ee blob + 0a94e51e387e1d2ef71134435d01043769fe9216 --- ftp.c +++ ftp.c @@ -708,15 +708,22 @@ static void cmd_cd(int argc, const char **argv) { struct qid qid; + int nfid; if (argc != 1) { printf("usage: cd remote-path\n"); return; } - if (walk_path(pwdfid, pwdfid, argv[0], &qid) == -1 || - !(qid.type & QTDIR)) + nfid = pwdfid+1; + if (walk_path(pwdfid, nfid, argv[0], &qid) == -1 || + !(qid.type & QTDIR)) { printf("can't cd %s\n", argv[0]); + do_clunk(nfid); + } else { + do_clunk(pwdfid); + pwdfid = nfid; + } } static void