X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=bin%2Fad%2Fad_util.c;h=897bdf3b1415c609efdae24f2104d019ef3464fc;hb=bb90c6c56688f908a1d93125fec0941e1c79fed5;hp=f951d25e9826698a9a89b65cef056b7163497d14;hpb=ea9e8d043fb0920e216f97e0ee9dc615a86a36d7;p=netatalk.git diff --git a/bin/ad/ad_util.c b/bin/ad/ad_util.c index f951d25e..897bdf3b 100644 --- a/bin/ad/ad_util.c +++ b/bin/ad/ad_util.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) 2009 Frank Lahm * Copyright (c) 1991, 1993, 1994 * The Regents of the University of California. All rights reserved. @@ -25,7 +25,7 @@ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. + * SUCH DAMAGE. */ #ifdef HAVE_CONFIG_H @@ -33,7 +33,6 @@ #endif /* HAVE_CONFIG_H */ #include -#include #include #include #include @@ -47,15 +46,27 @@ #include #include #include +#include + +#ifdef HAVE_SOLARIS_ACLS +#include +#endif /* HAVE_SOLARIS_ACLS */ +#ifdef HAVE_POSIX_ACLS +#include +#include +#endif /* HAVE_POSIX_ACLS */ + +#include #include -#include #include #include -#include #include #include #include +#include +#include + #include "ad.h" @@ -80,66 +91,64 @@ void _log(enum logtype lt, char *fmt, ...) /*! * Load volinfo and initialize struct vol * + * Only opens "dbd" volumes ! + * * @param path (r) path to evaluate - * @param vol (rw) structure to initialize -* + * @param vol (rw) structure to initialize + * * @returns 0 on success, exits on error */ -int openvol(const char *path, afpvol_t *vol) +int openvol(AFPObj *obj, const char *path, afpvol_t *vol) { int flags = 0; memset(vol, 0, sizeof(afpvol_t)); - /* try to find a .AppleDesktop/.volinfo */ - if (loadvolinfo((char *)path, &vol->volinfo) == 0) { - - if (vol_load_charsets(&vol->volinfo) == -1) - ERROR("Error loading charsets!"); - - /* Sanity checks to ensure we can touch this volume */ - if (vol->volinfo.v_adouble != AD_VERSION2) - ERROR("Unsupported adouble versions: %u", vol->volinfo.v_adouble); + if ((vol->vol = getvolbypath(obj, path)) == NULL) + return -1; - if (vol->volinfo.v_vfs_ea != AFPVOL_EA_SYS) - ERROR("Unsupported Extended Attributes option: %u", vol->volinfo.v_vfs_ea); + if (STRCMP(vol->vol->v_cnidscheme, != , "dbd")) + ERROR("\"%s\" isn't a \"dbd\" CNID volume!", vol->vol->v_path); - /* initialize sufficient struct vol for VFS initialisation */ - vol->volume.v_adouble = AD_VERSION2; - vol->volume.v_vfs_ea = AFPVOL_EA_SYS; - initvol_vfs(&vol->volume); + /* Sanity checks to ensure we can touch this volume */ + if (vol->vol->v_adouble != AD_VERSION2 + && vol->vol->v_adouble != AD_VERSION_EA) + ERROR("Unsupported adouble versions: %u", vol->vol->v_adouble); - if ((vol->volinfo.v_flags & AFPVOL_NODEV)) - flags |= CNID_FLAG_NODEV; + if (vol->vol->v_vfs_ea != AFPVOL_EA_SYS) + ERROR("Unsupported Extended Attributes option: %u", vol->vol->v_vfs_ea); - if ((vol->volume.v_cdb = cnid_open(vol->volinfo.v_dbpath, - 0000, - "dbd", - flags, - vol->volinfo.v_dbd_host, - vol->volinfo.v_dbd_port)) == NULL) - ERROR("Cant initialize CNID database connection for %s", vol->volinfo.v_path); + if ((vol->vol->v_flags & AFPVOL_NODEV)) + flags |= CNID_FLAG_NODEV; - cnid_getstamp(vol->volume.v_cdb, - vol->db_stamp, - sizeof(vol->db_stamp)); - } + if ((vol->vol->v_cdb = cnid_open(vol->vol->v_path, + 0000, + "dbd", + flags, + vol->vol->v_cnidserver, + vol->vol->v_cnidport)) == NULL) + ERROR("Cant initialize CNID database connection for %s", vol->vol->v_path); + cnid_getstamp(vol->vol->v_cdb, + vol->db_stamp, + sizeof(vol->db_stamp)); + return 0; } void closevol(afpvol_t *vol) { - if (vol->volume.v_cdb) - cnid_close(vol->volume.v_cdb); - + if (vol->vol->v_cdb) { + cnid_close(vol->vol->v_cdb); + vol->vol->v_cdb = NULL; + } memset(vol, 0, sizeof(afpvol_t)); } /* Taken form afpd/desktop.c */ -char *utompath(const struct volinfo *volinfo, const char *upath) +char *utompath(const struct vol *vol, const char *upath) { static char mpath[ MAXPATHLEN + 2]; /* for convert_charset dest_len parameter +2 */ char *m; @@ -154,76 +163,28 @@ char *utompath(const struct volinfo *volinfo, const char *upath) u = upath; outlen = strlen(upath); - if ((volinfo->v_casefold & AFPVOL_UTOMUPPER)) + if ((vol->v_casefold & AFPVOL_UTOMUPPER)) flags |= CONV_TOUPPER; - else if ((volinfo->v_casefold & AFPVOL_UTOMLOWER)) + else if ((vol->v_casefold & AFPVOL_UTOMLOWER)) flags |= CONV_TOLOWER; - if ((volinfo->v_flags & AFPVOL_EILSEQ)) { + if ((vol->v_flags & AFPVOL_EILSEQ)) { flags |= CONV__EILSEQ; } /* convert charsets */ - if ((size_t)-1 == ( outlen = convert_charset(volinfo->v_volcharset, + if ((size_t)-1 == ( outlen = convert_charset(vol->v_volcharset, CH_UTF8_MAC, - volinfo->v_maccharset, + vol->v_maccharset, u, outlen, mpath, MAXPATHLEN, &flags)) ) { SLOG("Conversion from %s to %s for %s failed.", - volinfo->v_volcodepage, volinfo->v_maccodepage, u); + vol->v_volcodepage, vol->v_maccodepage, u); return NULL; } return(m); } -/*! - * Build path relativ to volume root - * - * path might be: - * (a) relative: - * "dir/subdir" with cwd: "/afp_volume/topdir" - * (b) absolute: - * "/afp_volume/dir/subdir" - * - * @param path (r) path relative to cwd() or absolute - * @param volpath (r) volume path that path is a subdir of (has been computed in volinfo funcs) - * - * @returns relative path in new bstring, caller must bdestroy it - */ -static bstring rel_path_in_vol(const char *path, const char *volpath) -{ - EC_INIT; - - if (path == NULL || volpath == NULL) - return NULL; - - bstring fpath = NULL; - - /* Make path absolute by concetanating for case (a) */ - if (path[0] != '/') { - EC_NULL(fpath = bfromcstr(getcwdpath())); - if (bchar(fpath, blength(fpath) - 1) != '/') - EC_ZERO(bcatcstr(fpath, "/")); - EC_ZERO(bcatcstr(fpath, path)); - BSTRING_STRIP_SLASH(fpath); - } else { - EC_NULL(fpath = bfromcstr(path)); - BSTRING_STRIP_SLASH(fpath); - } - - /* - * Now we have eg: - * fpath: /Volume/netatalk/dir/bla - * volpath: /Volume/netatalk/ - * we want: "dir/bla" - */ - EC_ZERO(bdelete(fpath, 0, strlen(volpath))); - return fpath; - -EC_CLEANUP: - bdestroy(fpath); - return NULL; -} /*! * Convert dot encoding of basename _in place_ @@ -247,26 +208,18 @@ int convert_dots_encoding(const afpvol_t *svol, const afpvol_t *dvol, char *path int pos = bname - path; uint16_t flags = 0; - if ( ! svol->volinfo.v_path) { + if ( ! svol->vol->v_path) { /* no source volume: escape special chars (eg ':') */ - from = dvol->volinfo.v_volcharset; /* src = dst charset */ - flags |= CONV_ESCAPEHEX; + from = dvol->vol->v_volcharset; /* src = dst charset */ + if (dvol->vol->v_adouble == AD_VERSION2) + flags |= CONV_ESCAPEHEX; } else { - from = svol->volinfo.v_volcharset; - } - - if ( (svol->volinfo.v_path) - && ! (svol->volinfo.v_flags & AFPVOL_USEDOTS) - && (dvol->volinfo.v_flags & AFPVOL_USEDOTS)) { - /* source is without dots, destination is with */ - flags |= CONV_UNESCAPEHEX; - } else if (! (dvol->volinfo.v_flags & AFPVOL_USEDOTS)) { - flags |= CONV_ESCAPEDOTS; + from = svol->vol->v_volcharset; } int len = convert_charset(from, - dvol->volinfo.v_volcharset, - dvol->volinfo.v_maccharset, + dvol->vol->v_volcharset, + dvol->vol->v_maccharset, bname, strlen(bname), buf, MAXPATHLEN, &flags); @@ -287,22 +240,16 @@ int convert_dots_encoding(const afpvol_t *svol, const afpvol_t *dvol, char *path * (b) absolute: * "/afp_volume/dir/subdir" * - * 1) start recursive CNID search with - * a) DID:2 / "topdir" - * b) DID:2 / "dir" - * 2) ...until we have the CNID for - * a) "/afp_volume/topdir/dir" - * b) "/afp_volume/dir" (no recursion required) + * path MUST be pointing inside vol, this is usually the case as vol has been build from + * path using loadvolinfo and friends. * - * @param vi (r) pointer to volinfo struct - * @param vol (r) pointer to vol struct + * @param vol (r) pointer to afpvol_t * @param path (r) path, see above * @param did (rw) parent CNID of returned CNID * * @returns CNID of path */ -cnid_t cnid_for_path(const struct volinfo *vi, - const struct vol *vol, +cnid_t cnid_for_path(const afpvol_t *vol, const char *path, cnid_t *did) { @@ -314,26 +261,100 @@ cnid_t cnid_for_path(const struct volinfo *vi, struct bstrList *l = NULL; struct stat st; - cnid = *did = htonl(2); + cnid = htonl(2); - EC_NULL(rpath = rel_path_in_vol(path, vi->v_path)); - EC_NULL(statpath = bfromcstr(vi->v_path)); + EC_NULL(rpath = rel_path_in_vol(path, vol->vol->v_path)); + EC_NULL(statpath = bfromcstr(vol->vol->v_path)); + EC_ZERO(bcatcstr(statpath, "/")); l = bsplit(rpath, '/'); - for(int i = 0; i < l->qty ; i++) { + for (int i = 0; i < l->qty ; i++) { *did = cnid; + EC_ZERO(bconcat(statpath, l->entry[i])); - EC_ZERO_LOG(stat(cfrombstr(statpath), &st)); + EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st), + "lstat(rpath: %s, elem: %s): %s: %s", + cfrombstr(rpath), cfrombstr(l->entry[i]), + cfrombstr(statpath), strerror(errno)); + + if ((cnid = cnid_add(vol->vol->v_cdb, + &st, + *did, + cfrombstr(l->entry[i]), + blength(l->entry[i]), + 0)) == CNID_INVALID) { + EC_FAIL; + } + EC_ZERO(bcatcstr(statpath, "/")); + } - cnid = cnid_add(vol->v_cdb, - &st, - *did, - cfrombstr(l->entry[i]), - blength(l->entry[i]), - 0); +EC_CLEANUP: + bdestroy(rpath); + bstrListDestroy(l); + bdestroy(statpath); + if (ret != 0) + return CNID_INVALID; + return cnid; +} + +/*! + * Resolves CNID of a given paths parent directory + * + * path might be: + * (a) relative: + * "dir/subdir" with cwd: "/afp_volume/topdir" + * (b) absolute: + * "/afp_volume/dir/subdir" + * + * path MUST be pointing inside vol, this is usually the case as vol has been build from + * path using loadvolinfo and friends. + * + * @param vol (r) pointer to afpvol_t + * @param path (r) path, see above + * @param did (rw) parent CNID of returned CNID + * + * @returns CNID of path + */ +cnid_t cnid_for_paths_parent(const afpvol_t *vol, + const char *path, + cnid_t *did) +{ + EC_INIT; + + cnid_t cnid; + bstring rpath = NULL; + bstring statpath = NULL; + struct bstrList *l = NULL; + struct stat st; + + *did = htonl(1); + cnid = htonl(2); + + EC_NULL(rpath = rel_path_in_vol(path, vol->vol->v_path)); + EC_NULL(statpath = bfromcstr(vol->vol->v_path)); + + l = bsplit(rpath, '/'); + if (l->qty == 1) + /* only one path element, means parent dir cnid is volume root = 2 */ + goto EC_CLEANUP; + for (int i = 0; i < (l->qty - 1); i++) { + *did = cnid; + EC_ZERO(bconcat(statpath, l->entry[i])); + EC_ZERO_LOGSTR(lstat(cfrombstr(statpath), &st), + "lstat(rpath: %s, elem: %s): %s: %s", + cfrombstr(rpath), cfrombstr(l->entry[i]), + cfrombstr(statpath), strerror(errno)); + + if ((cnid = cnid_add(vol->vol->v_cdb, + &st, + *did, + cfrombstr(l->entry[i]), + blength(l->entry[i]), + 0)) == CNID_INVALID) { + EC_FAIL; + } EC_ZERO(bcatcstr(statpath, "/")); - } EC_CLEANUP: @@ -346,4 +367,3 @@ EC_CLEANUP: return cnid; } -