X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fdesktop.c;h=5c56977acd3fd30e6dea0659b40b68b19ac68898;hb=HEAD;hp=6019150360f4d8a56a6bff4ce1108e1eabab3e4e;hpb=7f6fd6a70865f976a0778d41d3142d07031b0076;p=netatalk.git diff --git a/etc/afpd/desktop.c b/etc/afpd/desktop.c index 60191503..5c56977a 100644 --- a/etc/afpd/desktop.c +++ b/etc/afpd/desktop.c @@ -31,6 +31,8 @@ #include #include #include +#include +#include #include "volume.h" #include "directory.h" @@ -38,6 +40,174 @@ #include "desktop.h" #include "mangle.h" +#define EXEC_MODE (S_IXGRP | S_IXUSR | S_IXOTH) + +int setdeskmode(const struct vol *vol, const mode_t mode) +{ + EC_INIT; + char wd[ MAXPATHLEN + 1]; + struct stat st; + char modbuf[ 12 + 1], *m; + struct dirent *deskp, *subp; + DIR *desk, *sub; + + if (!dir_rx_set(mode)) { + /* want to remove read and search access to owner it will screw the volume */ + return -1 ; + } + if ( getcwd( wd , MAXPATHLEN) == NULL ) { + return( -1 ); + } + + bstring dtpath = bfromcstr(vol->v_dbpath); + bcatcstr(dtpath, "/" APPLEDESKTOP); + + EC_NEG1( chdir(cfrombstr(dtpath)) ); + + if (( desk = opendir( "." )) == NULL ) { + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) ); + } + EC_FAIL; + } + for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) { + if ( strcmp( deskp->d_name, "." ) == 0 || + strcmp( deskp->d_name, ".." ) == 0 || strlen( deskp->d_name ) > 2 ) { + continue; + } + strcpy( modbuf, deskp->d_name ); + strcat( modbuf, "/" ); + m = strchr( modbuf, '\0' ); + if (( sub = opendir( deskp->d_name )) == NULL ) { + continue; + } + for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) { + if ( strcmp( subp->d_name, "." ) == 0 || + strcmp( subp->d_name, ".." ) == 0 ) { + continue; + } + *m = '\0'; + strcat( modbuf, subp->d_name ); + /* XXX: need to preserve special modes */ + if (lstat(modbuf, &st) < 0) { + LOG(log_error, logtype_afpd, "setdeskmode: stat %s: %s",fullpathname(modbuf), strerror(errno) ); + continue; + } + + if (S_ISDIR(st.st_mode)) { + if (ochmod(modbuf, + DIRBITS | mode, + &st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0 && errno != EPERM) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) ); + } + } else if (ochmod(modbuf, + mode & ~EXEC_MODE, + &st, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0 && errno != EPERM) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) ); + } + + } + closedir( sub ); + /* XXX: need to preserve special modes */ + if (ochmod(deskp->d_name, + DIRBITS | mode, + NULL, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0 && errno != EPERM) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(deskp->d_name), strerror(errno) ); + } + } + closedir( desk ); + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) ); + EC_FAIL; + } + /* XXX: need to preserve special modes */ + if (ochmod(bdata(dtpath), + DIRBITS | mode, + NULL, + vol_syml_opt(vol) | vol_chmod_opt(vol) + ) < 0 && errno != EPERM) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", bdata(dtpath), strerror(errno)); + } + +EC_CLEANUP: + bdestroy(dtpath); + EC_EXIT; +} + +int setdeskowner(const struct vol *vol, uid_t uid, gid_t gid) +{ + EC_INIT; + char wd[ MAXPATHLEN + 1]; + char modbuf[12 + 1], *m; + struct dirent *deskp, *subp; + DIR *desk, *sub; + + if ( getcwd( wd, MAXPATHLEN ) == NULL ) { + return( -1 ); + } + + bstring dtpath = bfromcstr(vol->v_dbpath); + bcatcstr(dtpath, "/" APPLEDESKTOP); + + EC_NEG1( chdir(cfrombstr(dtpath)) ); + + if (( desk = opendir( "." )) == NULL ) { + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) ); + } + EC_FAIL; + } + for ( deskp = readdir( desk ); deskp != NULL; deskp = readdir( desk )) { + if ( strcmp( deskp->d_name, "." ) == 0 || + strcmp( deskp->d_name, ".." ) == 0 || + strlen( deskp->d_name ) > 2 ) { + continue; + } + strcpy( modbuf, deskp->d_name ); + strcat( modbuf, "/" ); + m = strchr( modbuf, '\0' ); + if (( sub = opendir( deskp->d_name )) == NULL ) { + continue; + } + for ( subp = readdir( sub ); subp != NULL; subp = readdir( sub )) { + if ( strcmp( subp->d_name, "." ) == 0 || + strcmp( subp->d_name, ".." ) == 0 ) { + continue; + } + *m = '\0'; + strcat( modbuf, subp->d_name ); + /* XXX: add special any uid, ignore group bits */ + if ( chown( modbuf, uid, gid ) < 0 && errno != EPERM ) { + LOG(log_error, logtype_afpd, "setdeskown: chown %s: %s", fullpathname(modbuf), strerror(errno) ); + } + } + closedir( sub ); + /* XXX: add special any uid, ignore group bits */ + if ( chown( deskp->d_name, uid, gid ) < 0 && errno != EPERM ) { + LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s", + deskp->d_name, strerror(errno) ); + } + } + closedir( desk ); + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) ); + EC_FAIL; + } + if (chown(cfrombstr(dtpath), uid, gid ) < 0 && errno != EPERM ) { + LOG(log_error, logtype_afpd, "setdeskowner: chown %s: %s", fullpathname(".AppleDouble"), strerror(errno) ); + } + +EC_CLEANUP: + bdestroy(dtpath); + EC_EXIT; +} + static void create_appledesktop_folder(const struct vol * vol) { bstring olddtpath = NULL, dtpath = NULL; @@ -50,11 +220,11 @@ static void create_appledesktop_folder(const struct vol * vol) dtpath = bfromcstr(vol->v_dbpath); bcatcstr(dtpath, "/" APPLEDESKTOP); - if (lstat(bdata(dtpath), &st) != 0) { + if (lstat(cfrombstr(dtpath), &st) != 0) { become_root(); - if (lstat(bdata(olddtpath), &st) == 0) { + if (lstat(cfrombstr(olddtpath), &st) == 0) { cmd_argv[0] = "mv"; cmd_argv[1] = bdata(olddtpath); cmd_argv[2] = bdata(dtpath); @@ -62,10 +232,10 @@ static void create_appledesktop_folder(const struct vol * vol) if (run_cmd("mv", cmd_argv) != 0) { LOG(log_error, logtype_afpd, "moving .AppleDesktop from \"%s\" to \"%s\" failed", bdata(olddtpath), bdata(dtpath)); - mkdir(bdata(dtpath), 0777); + mkdir(cfrombstr(dtpath), 0777); } } else { - mkdir(bdata(dtpath), 0777); + mkdir(cfrombstr(dtpath), 0777); } unbecome_root(); @@ -485,15 +655,17 @@ int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t return AFPERR_PARAM; } +#ifndef WITH_SENDFILE if ((buflen = dsi_readinit(dsi, rbuf, buflen, rc, AFP_OK)) < 0) goto geticon_exit; +#endif *rbuflen = buflen; /* do to the streaming nature, we have to exit if we encounter * a problem. much confusion results otherwise. */ while (*rbuflen > 0) { #ifdef WITH_SENDFILE - if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) { + if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize, AFP_OK) < 0) { switch (errno) { case ENOSYS: case EINVAL: /* there's no guarantee that all fs support sendfile */ @@ -675,7 +847,7 @@ static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, } isadir = path_isadir(path); - if (isadir || !(of = of_findname(path))) { + if (isadir || !(of = of_findname(vol, path))) { ad_init(&ad, vol); adp = &ad; } else @@ -750,7 +922,7 @@ static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t upath = path->u_name; isadir = path_isadir(path); - if (isadir || !(of = of_findname(path))) { + if (isadir || !(of = of_findname(vol, path))) { ad_init(&ad, vol); adp = &ad; } else @@ -827,7 +999,7 @@ static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path) } isadir = path_isadir(path); - if (isadir || !(of = of_findname(path))) { + if (isadir || !(of = of_findname(vol, path))) { ad_init(&ad, vol); adp = &ad; } else