The pathwalk() function is called only by connect_msg_to_attr() and by the rename function (c_rename(), which we'll see later). Let's look at this lowest-level function first, and then we'll proceed up the call hierarchy.
int pathwalk (resmgr_context_t *ctp, char *pathname, cfs_attr_t *mountpoint, int flags, des_t *output, int *nrets, struct _client_info *cinfo) { int nels; int sts; char *p; // 1) first, we break apart the slash-separated pathname memset (output, 0, sizeof (output [0]) * *nrets); output [0].attr = mountpoint; output [0].name = ""; nels = 1; for (p = strtok (pathname, "/"); p; p = strtok (NULL, "/")) { if (nels >= *nrets) { return (E2BIG); } output [nels].name = p; output [nels].attr = NULL; nels++ } // 2) next, we analyze each pathname for (*nrets = 1; *nrets < nels; ++*nrets) { // 3) only directories can have children. if (!S_ISDIR (output [*nrets - 1].attr -> attr.mode)) { return (ENOTDIR); } // 4) check access permissions sts = iofunc_check_access (ctp, &output [*nrets-1].attr -> attr, S_IEXEC, cinfo); if (sts != EOK) { return (sts); } // 5) search for the entry output [*nrets].attr = search_dir (output [*nrets].name, output [*nrets-1].attr); if (!output [*nrets].attr) { ++*nrets; return (ENOENT); } // 6) process the entry if (S_ISLNK (output [*nrets].attr -> attr.mode)) { ++*nrets; return (EOK); } } // 7) everything was okay return (EOK); }
The pathwalk() function fills the output parameter with the pathnames and attributes structures of each pathname component. The *nrets parameter is used as both an input and an output. In the input case it tells pathwalk() how big the output array is, and when pathwalk() returns, *nrets is used to indicate how many elements were successfully processed (see the walkthrough below). Note that the way that we've broken the string into pieces first, and then processed the individual components one at a time means that when we abort the function (for any of a number of reasons as described in the walkthrough), the output array may have elements that are valid past where the *nrets variable indicates. This is actually useful; for example, it lets us get the pathname of a file or directory that we're creating (and hence doesn't exist). It also lets us check if there are additional components past the one that we're creating, which would be an error.
Detailed walkthrough:
The job of *nrets is to give the higher-level routines an indication of where the processing stopped. The return value from pathwalk() will tell them why it stopped.