X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Fdesktop.c;h=5c56977acd3fd30e6dea0659b40b68b19ac68898;hp=96e2fccf2f04b0e24634a8ddf314cd2af4079a87;hb=c72d10d6f92fe81d040ab983768d7fdccea7fb2e;hpb=2fdd522410f80afcd055d7333f491ee6c0b4b9fa diff --git a/etc/afpd/desktop.c b/etc/afpd/desktop.c index 96e2fccf..5c56977a 100644 --- a/etc/afpd/desktop.c +++ b/etc/afpd/desktop.c @@ -28,12 +28,222 @@ #include #include #include +#include +#include +#include +#include +#include + #include "volume.h" #include "directory.h" #include "fork.h" #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; + 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(cfrombstr(dtpath), &st) != 0) { + + become_root(); + + if (lstat(cfrombstr(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(cfrombstr(dtpath), 0777); + } + } else { + mkdir(cfrombstr(dtpath), 0777); + } + + unbecome_root(); + } + + bdestroy(dtpath); + bdestroy(olddtpath); +} int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen) { @@ -48,6 +258,8 @@ int afp_opendt(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, size return( AFPERR_PARAM ); } + create_appledesktop_folder(vol); + memcpy( rbuf, &vid, sizeof(vid)); *rbuflen = sizeof(vid); return( AFP_OK ); @@ -204,42 +416,34 @@ int afp_addicon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t */ addicon_err: if ( cc < 0 ) { - if (obj->proto == AFPPROTO_DSI) { - dsi_writeinit(obj->handle, rbuf, buflen); - dsi_writeflush(obj->handle); - } + dsi_writeinit(obj->dsi, rbuf, buflen); + dsi_writeflush(obj->dsi); return cc; } - switch (obj->proto) { - case AFPPROTO_DSI: - { - DSI *dsi = obj->handle; + DSI *dsi = obj->dsi; - iovcnt = dsi_writeinit(dsi, rbuf, buflen); + iovcnt = dsi_writeinit(dsi, rbuf, buflen); - /* add headers at end of file */ - if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) { - LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno)); - dsi_writeflush(dsi); - return AFPERR_PARAM; - } + /* add headers at end of file */ + if ((cc == 0) && (write(si.sdt_fd, imh, sizeof(imh)) < 0)) { + LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno)); + dsi_writeflush(dsi); + return AFPERR_PARAM; + } - if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) { - LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno)); - dsi_writeflush(dsi); - return AFPERR_PARAM; - } + if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) { + LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno)); + dsi_writeflush(dsi); + return AFPERR_PARAM; + } - while ((iovcnt = dsi_write(dsi, rbuf, buflen))) { - if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) { - LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno)); - dsi_writeflush(dsi); - return AFPERR_PARAM; - } - } + while ((iovcnt = dsi_write(dsi, rbuf, buflen))) { + if ((cc = write(si.sdt_fd, rbuf, iovcnt)) < 0) { + LOG(log_error, logtype_afpd, "afp_addicon(%s): write: %s", icon_dtfile(vol, fcreator), strerror(errno)); + dsi_writeflush(dsi); + return AFPERR_PARAM; } - break; } close( si.sdt_fd ); @@ -441,8 +645,8 @@ int afp_geticon(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t #define min(a,b) ((a)<(b)?(a):(b)) rc = min( bsize, rsize ); - if ((obj->proto == AFPPROTO_DSI) && (buflen < rc)) { - DSI *dsi = obj->handle; + if (buflen < rc) { + DSI *dsi = obj->dsi; struct stat st; off_t size; @@ -451,29 +655,29 @@ 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 (!obj->options.flags & OPTION_DEBUG) { - if (dsi_stream_read_file(dsi, si.sdt_fd, offset, dsi->datasize) < 0) { - switch (errno) { - case ENOSYS: - case EINVAL: /* there's no guarantee that all fs support sendfile */ - break; - default: - goto geticon_exit; - } - } - else { - dsi_readdone(dsi); - return AFP_OK; + 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 */ + break; + default: + goto geticon_exit; } } + else { + dsi_readdone(dsi); + return AFP_OK; + } #endif buflen = read(si.sdt_fd, rbuf, *rbuflen); if (buflen < 0) @@ -513,8 +717,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++ ) ; @@ -626,7 +830,7 @@ utompath_error: } /* ------------------------- */ -static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf) +static int ad_addcomment(const AFPObj *obj, struct vol *vol, struct path *path, char *ibuf) { struct ofork *of; char *name, *upath; @@ -638,20 +842,19 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf) clen = min( clen, 199 ); upath = path->u_name; - if (check_access(upath, OPENACC_WR ) < 0) { + if (check_access(obj, vol, upath, OPENACC_WR ) < 0) { return AFPERR_ACCESS; } isadir = path_isadir(path); - if (isadir || !(of = of_findname(path))) { - ad_init(&ad, vol->v_adouble, vol->v_ad_options); + if (isadir || !(of = of_findname(vol, path))) { + ad_init(&ad, vol); adp = &ad; } else adp = of->of_ad; if (ad_open(adp, upath, - ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0), - O_CREAT | O_RDWR, + ADFLAGS_HF | ( (isadir) ? ADFLAGS_DIR : 0) | ADFLAGS_CREATE | ADFLAGS_RDWR, 0666) < 0 ) { return( AFPERR_ACCESS ); } @@ -669,12 +872,12 @@ static int ad_addcomment(struct vol *vol, struct path *path, char *ibuf) memcpy( ad_entry( adp, ADEID_COMMENT ), ibuf, clen ); ad_flush( adp ); } - ad_close_metadata( adp); + ad_close(adp, ADFLAGS_HF); return( AFP_OK ); } /* ----------------------------- */ -int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +int afp_addcomment(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { struct vol *vol; struct dir *dir; @@ -705,7 +908,7 @@ int afp_addcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _ ibuf++; } - return ad_addcomment(vol, path, ibuf); + return ad_addcomment(obj, vol, path, ibuf); } /* -------------------- */ @@ -719,8 +922,8 @@ 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))) { - ad_init(&ad, vol->v_adouble, vol->v_ad_options); + if (isadir || !(of = of_findname(vol, path))) { + ad_init(&ad, vol); adp = &ad; } else adp = of->of_ad; @@ -730,7 +933,7 @@ static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t } if (!ad_getentryoff(adp, ADEID_COMMENT)) { - ad_close_metadata( adp ); + ad_close(adp, ADFLAGS_HF); return AFPERR_NOITEM; } /* @@ -738,7 +941,7 @@ static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t */ if ( ad_getentrylen( adp, ADEID_COMMENT ) <= 0 || ad_getentrylen( adp, ADEID_COMMENT ) > 199 ) { - ad_close_metadata( adp ); + ad_close(adp, ADFLAGS_HF); return( AFPERR_NOITEM ); } @@ -746,7 +949,7 @@ static int ad_getcomment(struct vol *vol, struct path *path, char *rbuf, size_t *rbuf++ = clen; memcpy( rbuf, ad_entry( adp, ADEID_COMMENT ), clen); *rbuflen = clen + 1; - ad_close_metadata( adp); + ad_close(adp, ADFLAGS_HF); return( AFP_OK ); } @@ -783,7 +986,7 @@ int afp_getcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf, } /* ----------------------- */ -static int ad_rmvcomment(struct vol *vol, struct path *path) +static int ad_rmvcomment(const AFPObj *obj, struct vol *vol, struct path *path) { struct adouble ad, *adp; struct ofork *of; @@ -791,18 +994,18 @@ static int ad_rmvcomment(struct vol *vol, struct path *path) char *upath; upath = path->u_name; - if (check_access(upath, OPENACC_WR ) < 0) { + if (check_access(obj, vol, upath, OPENACC_WR ) < 0) { return AFPERR_ACCESS; } isadir = path_isadir(path); - if (isadir || !(of = of_findname(path))) { - ad_init(&ad, vol->v_adouble, vol->v_ad_options); + if (isadir || !(of = of_findname(vol, path))) { + ad_init(&ad, vol); adp = &ad; } else adp = of->of_ad; - if ( ad_open(adp, upath, ADFLAGS_HF | (isadir) ? ADFLAGS_DIR : 0, 0) < 0 ) { + if ( ad_open(adp, upath, ADFLAGS_HF | ADFLAGS_RDWR | ((isadir) ? ADFLAGS_DIR : 0)) < 0 ) { switch ( errno ) { case ENOENT : return( AFPERR_NOITEM ); @@ -817,7 +1020,7 @@ static int ad_rmvcomment(struct vol *vol, struct path *path) ad_setentrylen( adp, ADEID_COMMENT, 0 ); ad_flush( adp ); } - ad_close_metadata( adp); + ad_close(adp, ADFLAGS_HF); return( AFP_OK ); } @@ -849,5 +1052,5 @@ int afp_rmvcomment(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _ return get_afp_errno(AFPERR_NOOBJ); } - return ad_rmvcomment(vol, s_path); + return ad_rmvcomment(obj, vol, s_path); }