X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fdesktop.c;h=c437b7e6b4adb92f2a2c03388b401b3ad2eb8082;hb=321a0107c48da7b3fbf895a2b32244174c1ff39c;hp=2a408467f1591badfe13eac47ea339c4e3484b0c;hpb=daeaf4d0d2d849af86d8578d9c6e41a7aada9640;p=netatalk.git diff --git a/etc/afpd/desktop.c b/etc/afpd/desktop.c index 2a408467..c437b7e6 100644 --- a/etc/afpd/desktop.c +++ b/etc/afpd/desktop.c @@ -30,6 +30,8 @@ #include #include #include +#include +#include #include "volume.h" #include "directory.h" @@ -37,109 +39,193 @@ #include "desktop.h" #include "mangle.h" -typedef struct _special_folder { - const char *name; - int precreate; - mode_t mode; - int hide; -} _special_folder; +#define EXEC_MODE (S_IXGRP | S_IXUSR | S_IXOTH) -static const _special_folder special_folders[] = { - {".AppleDesktop", 1, 0777, 0}, - {NULL, 0, 0, 0}}; - -/* - * precreate a folder - * this is only intended for folders in the volume root - * It will *not* work if the folder name contains extended characters - */ -static int create_special_folder (const struct vol *vol, const struct _special_folder *folder) +int setdeskmode(const struct vol *vol, const mode_t mode) { - char *p,*q,*r; - struct adouble ad; - uint16_t attr; - struct stat st; - int ret; - - - p = (char *) malloc ( strlen(vol->v_path)+strlen(folder->name)+2); - if ( p == NULL) { - LOG(log_error, logtype_afpd,"malloc failed"); - exit (EXITERR_SYS); + 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 ; } - - q=strdup(folder->name); - if ( q == NULL) { - LOG(log_error, logtype_afpd,"malloc failed"); - exit (EXITERR_SYS); + if ( getcwd( wd , MAXPATHLEN) == NULL ) { + return( -1 ); } - strcpy(p, vol->v_path); - strcat(p, "/"); + bstring dtpath = bfromcstr(vol->v_dbpath); + bcatcstr(dtpath, "/" APPLEDESKTOP); + + EC_NEG1( chdir(bdata(dtpath)) ); - r=q; - while (*r) { - if ((vol->v_casefold & AFPVOL_MTOUUPPER)) - *r=toupper(*r); - else if ((vol->v_casefold & AFPVOL_MTOULOWER)) - *r=tolower(*r); - r++; + if (( desk = opendir( "." )) == NULL ) { + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskmode: chdir %s: %s", wd, strerror(errno) ); + } + EC_FAIL; } - strcat(p, q); + 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 ( (ret = stat( p, &st )) < 0 ) { - if (folder->precreate) { - if (ad_mkdir(p, folder->mode)) { - LOG(log_debug, logtype_afpd,"Creating '%s' failed in %s: %s", p, vol->v_path, strerror(errno)); - free(p); - free(q); - return -1; + if (S_ISDIR(st.st_mode)) { + if ( chmod_acl( modbuf, (DIRBITS | mode)) < 0 && errno != EPERM ) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) ); + } + } else if ( chmod_acl( modbuf, mode & ~EXEC_MODE ) < 0 && errno != EPERM ) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s",fullpathname(modbuf), strerror(errno) ); } - ret = 0; + + } + closedir( sub ); + /* XXX: need to preserve special modes */ + if ( chmod_acl( deskp->d_name, (DIRBITS | mode)) < 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 ( chmod_acl(bdata(dtpath), (DIRBITS | mode)) < 0 && errno != EPERM ) { + LOG(log_error, logtype_afpd, "setdeskmode: chmod %s: %s", bdata(dtpath), strerror(errno)); + } - if ( !ret && folder->hide) { - /* Hide it */ - ad_init(&ad, vol); - if (ad_open(&ad, p, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0) { - free(p); - free(q); - return (-1); - } +EC_CLEANUP: + bdestroy(dtpath); + EC_EXIT; +} - ad_setname(&ad, folder->name); +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 ); + } - ad_getattr(&ad, &attr); - attr |= htons( ntohs( attr ) | ATTRBIT_INVISIBLE ); - ad_setattr(&ad, attr); + bstring dtpath = bfromcstr(vol->v_dbpath); + bcatcstr(dtpath, "/" APPLEDESKTOP); - /* do the same with the finder info */ - if (ad_entry(&ad, ADEID_FINDERI)) { - memcpy(&attr, ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, sizeof(attr)); - attr |= htons(FINDERINFO_INVISIBLE); - memcpy(ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF,&attr, sizeof(attr)); + EC_NEG1( chdir(bdata(dtpath)) ); + + if (( desk = opendir( "." )) == NULL ) { + if ( chdir( wd ) < 0 ) { + LOG(log_error, logtype_afpd, "setdeskowner: chdir %s: %s", wd, strerror(errno) ); } - - ad_flush(&ad); - ad_close(&ad, ADFLAGS_HF); + EC_FAIL; } - free(p); - free(q); - return 0; + 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(bdata(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) { - const _special_folder *p = &special_folders[0]; + bstring olddtpath = NULL, dtpath = NULL; + struct stat st; + char *cmd_argv[4]; + + olddtpath = bfromcstr(vol->v_path); + bcatcstr(olddtpath, "/" APPLEDESKTOP); + + dtpath = bfromcstr(vol->v_dbpath); + bcatcstr(dtpath, "/" APPLEDESKTOP); + + if (lstat(bdata(dtpath), &st) != 0) { - become_root(); + become_root(); - for (; p->name != NULL; p++) { - create_special_folder (vol, p); + if (lstat(bdata(olddtpath), &st) == 0) { + cmd_argv[0] = "mv"; + cmd_argv[1] = bdata(olddtpath); + cmd_argv[2] = bdata(dtpath); + cmd_argv[3] = NULL; + 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); + } + } else { + mkdir(bdata(dtpath), 0777); + } + + unbecome_root(); } - unbecome_root(); + bdestroy(dtpath); + bdestroy(olddtpath); } int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) @@ -552,15 +638,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 */ @@ -612,8 +700,8 @@ char *dtfile(const struct vol *vol, u_char creator[], char *ext ) char *p; unsigned int i; - strcpy( path, vol->v_path ); - strcat( path, "/.AppleDesktop/" ); + strcpy( path, vol->v_dbpath ); + strcat( path, "/" APPLEDESKTOP "/" ); for ( p = path; *p != '\0'; p++ ) ;