2 * Copyright (c) 2009 Frank Lahm <franklahm@gmail.com>
3 * Copyright (c) 1991, 1993, 1994
4 * The Regents of the University of California. All rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 4. Neither the name of the University nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33 #endif /* HAVE_CONFIG_H */
35 #include <sys/types.h>
36 #include <sys/param.h>
38 #include <arpa/inet.h>
49 #include <atalk/util.h>
50 #include <atalk/cnid.h>
51 #include <atalk/bstrlib.h>
52 #include <atalk/bstradd.h>
53 #include <atalk/logger.h>
54 #include <atalk/errchk.h>
55 #include <atalk/unicode.h>
58 * Build path relativ to volume root
62 * "dir/subdir" with cwd: "/afp_volume/topdir"
64 * "/afp_volume/dir/subdir"
66 * @param path (r) path relative to cwd() or absolute
67 * @param volpath (r) volume path that path is a subdir of (has been computed in volinfo funcs)
69 * @returns relative path in new bstring, caller must bdestroy it
71 bstring rel_path_in_vol(const char *path, const char *volpath)
79 if (path == NULL || volpath == NULL)
82 EC_NEG1_LOG(cwd = open(".", O_RDONLY));
84 EC_ZERO_LOGSTR(lstat(path, &st), "lstat(%s): %s", path, strerror(errno));
87 EC_NULL(fpath = bfromcstr(path));
89 switch (S_IFMT & st.st_mode) {
92 EC_NULL_LOG(dname = strdup(path));
93 EC_ZERO_LOGSTR(chdir(dirname(dname)), "chdir(%s): %s", dirname, strerror(errno));
96 EC_NULL(fpath = bfromcstr(getcwdpath()));
97 BSTRING_STRIP_SLASH(fpath);
98 EC_ZERO(bcatcstr(fpath, "/"));
99 EC_NULL_LOG(dname = strdup(path));
100 EC_ZERO(bcatcstr(fpath, basename(dname)));
104 EC_ZERO_LOGSTR(chdir(path), "chdir(%s): %s", path, strerror(errno));
105 EC_NULL(fpath = bfromcstr(getcwdpath()));
113 BSTRING_STRIP_SLASH(fpath);
117 * fpath: /Volume/netatalk/dir/bla
118 * volpath: /Volume/netatalk/
121 int len = strlen(volpath);
122 if (volpath[len-1] != '/')
123 /* in case volpath has no trailing slash */
125 EC_ZERO(bdelete(fpath, 0, len));
128 if (dname) free(dname);
139 * Resolves CNID of a given path
143 * "dir/subdir" with cwd: "/afp_volume/topdir"
145 * "/afp_volume/dir/subdir"
147 * path MUST be pointing inside vol, this is usually the case as vol has been build from
148 * path using loadvolinfo and friends.
150 * @param cdb (r) CNID db handle
151 * @param volpath (r) UNIX path of volume
152 * @param path (r) path, see above
153 * @param did (w) parent CNID of returned CNID
155 * @returns CNID of path
157 cnid_t cnid_for_path(struct _cnid_db *cdb,
165 bstring rpath = NULL;
166 bstring statpath = NULL;
167 struct bstrList *l = NULL;
172 EC_NULL(rpath = rel_path_in_vol(path, volpath));
173 EC_NULL(statpath = bfromcstr(volpath));
174 EC_ZERO(bcatcstr(statpath, "/"));
176 l = bsplit(rpath, '/');
177 for (int i = 0; i < l->qty ; i++) {
180 EC_ZERO(bconcat(statpath, l->entry[i]));
181 EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st),
182 "lstat(rpath: %s, elem: %s): %s: %s",
183 cfrombstr(rpath), cfrombstr(l->entry[i]),
184 cfrombstr(statpath), strerror(errno));
186 if ((cnid = cnid_add(cdb,
189 cfrombstr(l->entry[i]),
190 blength(l->entry[i]),
191 0)) == CNID_INVALID) {
194 EC_ZERO(bcatcstr(statpath, "/"));