X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=etc%2Fafpd%2Fvolume.c;h=50945539cffa78c09fc8e2d46e18a370c2611fea;hb=b362b6f7b22b6e4e9e74760989f389149677917b;hp=2677504d80be4796ab6093d66031d859a38eaa76;hpb=db0d88c59bdd428d33a05e06e49fbd8b75c5fac9;p=netatalk.git diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index 2677504d..50945539 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -35,6 +35,8 @@ char *strchr (), *strrchr (); #include #include #include +#include +#include #include #include @@ -47,13 +49,15 @@ char *strchr (), *strrchr (); #include #include #include - +#include +#include +#include +#include #ifdef CNID_DB #include #endif /* CNID_DB*/ -#include "globals.h" #include "directory.h" #include "file.h" #include "volume.h" @@ -69,17 +73,6 @@ extern int afprun(int root, char *cmd, int *outfd); #define MIN(a, b) ((a) < (b) ? (a) : (b)) #endif /* ! MIN */ -#ifndef NO_LARGE_VOL_SUPPORT -#if BYTE_ORDER == BIG_ENDIAN -#define hton64(x) (x) -#define ntoh64(x) (x) -#else /* BYTE_ORDER == BIG_ENDIAN */ -#define hton64(x) ((u_int64_t) (htonl(((x) >> 32) & 0xffffffffLL)) | \ - (u_int64_t) ((htonl(x) & 0xffffffffLL) << 32)) -#define ntoh64(x) (hton64(x)) -#endif /* BYTE_ORDER == BIG_ENDIAN */ -#endif /* ! NO_LARGE_VOL_SUPPORT */ - #ifndef UUID_PRINTABLE_STRING_LENGTH #define UUID_PRINTABLE_STRING_LENGTH 37 #endif @@ -167,6 +160,8 @@ static void handle_special_folders (const struct vol *); static void deletevol(struct vol *vol); static void volume_free(struct vol *vol); static void check_ea_sys_support(struct vol *vol); +static char *get_vol_uuid(const AFPObj *obj, const char *volname); +static int readvolfile(AFPObj *obj, struct afp_volume_name *p1,char *p2, int user, struct passwd *pwent); static void volfree(struct vol_option *options, const struct vol_option *save) { @@ -271,6 +266,7 @@ static char *volxlate(AFPObj *obj, } else if (is_var(p, "$c")) { if (afpmaster && xlatevolname) return NULL; +#ifndef NO_DDP if (obj->proto == AFPPROTO_ASP) { ASP asp = obj->handle; @@ -279,7 +275,9 @@ static char *volxlate(AFPObj *obj, dest += len; destlen -= len; - } else if (obj->proto == AFPPROTO_DSI) { + } +#endif + if (obj->proto == AFPPROTO_DSI) { DSI *dsi = obj->handle; len = sprintf(dest, "%s:%u", getip_string((struct sockaddr *)&dsi->client), @@ -308,14 +306,16 @@ static char *volxlate(AFPObj *obj, } else if (is_var(p, "$i")) { if (afpmaster && xlatevolname) return NULL; +#ifndef NO_DDP if (obj->proto == AFPPROTO_ASP) { ASP asp = obj->handle; - len = sprintf(dest, "%u", ntohs(asp->asp_sat.sat_addr.s_net)); dest += len; destlen -= len; - } else if (obj->proto == AFPPROTO_DSI) { + } +#endif + if (obj->proto == AFPPROTO_DSI) { DSI *dsi = obj->handle; q = getip_string((struct sockaddr *)&dsi->client); } @@ -509,11 +509,12 @@ static void volset(struct vol_option *options, struct vol_option *save, options[VOLOPT_FLAGS].i_value |= AFPVOL_TM; else if (strcasecmp(p, "searchdb") == 0) options[VOLOPT_FLAGS].i_value |= AFPVOL_SEARCHDB; -/* Found this in branch dir-rewrite, maybe we want to use it sometimes */ -#if 0 - else if (strcasecmp(p, "cdrom") == 0) - options[VOLOPT_FLAGS].i_value |= AFPVOL_CDROM | AFPVOL_RO; -#endif + else if (strcasecmp(p, "nonetids") == 0) + options[VOLOPT_FLAGS].i_value |= AFPVOL_NONETIDS; + else if (strcasecmp(p, "noacls") == 0) + options[VOLOPT_FLAGS].i_value &= ~AFPVOL_ACLS; + else if (strcasecmp(p, "followsymlinks") == 0) + options[VOLOPT_FLAGS].i_value |= AFPVOL_FOLLOWSYM; p = strtok(NULL, ","); } @@ -672,7 +673,14 @@ static int creatvol(AFPObj *obj, struct passwd *pwd, if ( (flags & CONV_REQMANGLE) || (tmpvlen > AFPVOL_MACNAMELEN)) { if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) { flags = CONV_FORCE; - tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_MACNAMELEN - suffixlen, &flags); + tmpvlen = convert_charset(obj->options.unixcharset, + obj->options.maccharset, + 0, + name, + vlen, + tmpname, + AFPVOL_MACNAMELEN - suffixlen, + &flags); tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0; } strcat(tmpname, suffix); @@ -680,14 +688,24 @@ static int creatvol(AFPObj *obj, struct passwd *pwd, } /* Secondly convert name from maccharset to UCS2 */ - if ( 0 >= ( macvlen = convert_string(obj->options.maccharset, CH_UCS2, tmpname, tmpvlen, mactmpname, AFPVOL_U8MNAMELEN*2)) ) + if ( 0 >= ( macvlen = convert_string(obj->options.maccharset, + CH_UCS2, + tmpname, + tmpvlen, + mactmpname, + AFPVOL_U8MNAMELEN*2)) ) return -1; LOG(log_maxdebug, logtype_afpd, "createvol: Volume '%s' -> Longname: '%s'", name, tmpname); /* check duplicate */ for ( volume = Volumes; volume; volume = volume->v_next ) { - if (( strcasecmp_w( volume->v_u8mname, u8mtmpname ) == 0 ) || ( strcasecmp_w( volume->v_macname, mactmpname ) == 0 )){ + if ((utf8_encoding() && (strcasecmp_w(volume->v_u8mname, u8mtmpname) == 0)) + || + (!utf8_encoding() && (strcasecmp_w(volume->v_macname, mactmpname) == 0))) { + LOG (log_error, logtype_afpd, + "Duplicate volume name, check AppleVolumes files: previous: \"%s\", new: \"%s\"", + volume->v_localname, name); if (volume->v_deleted) { volume->v_new = hide = 1; } @@ -737,9 +755,10 @@ static int creatvol(AFPObj *obj, struct passwd *pwd, volume->v_vid = ++lastvid; volume->v_vid = htons(volume->v_vid); #ifdef HAVE_ACLS - if (check_vol_acl_support(volume)) - volume->v_flags |= AFPVOL_ACLS -; + if (!check_vol_acl_support(volume)) { + LOG(log_debug, logtype_afpd, "creatvol(\"%s\"): disabling ACL support", volume->v_path); + options[VOLOPT_FLAGS].i_value &= ~AFPVOL_ACLS; + } #endif /* handle options */ @@ -761,6 +780,8 @@ static int creatvol(AFPObj *obj, struct passwd *pwd, volume->v_ad_options |= ADVOL_INVDOTS; if ((volume->v_flags & AFPVOL_NOADOUBLE)) volume->v_ad_options |= ADVOL_NOADOUBLE; + if ((volume->v_flags & AFPVOL_FOLLOWSYM)) + volume->v_ad_options |= ADVOL_FOLLO_SYML; if (options[VOLOPT_PASSWORD].c_value) volume->v_password = strdup(options[VOLOPT_PASSWORD].c_value); @@ -867,9 +888,9 @@ static int creatvol(AFPObj *obj, struct passwd *pwd, check_ea_sys_support(volume); initvol_vfs(volume); - /* get/store uuid from file */ - if (volume->v_flags & AFPVOL_TM) { - char *uuid = get_uuid(obj, volume->v_localname); + /* get/store uuid from file in afpd master*/ + if ((parent_or_child == 0) && (volume->v_flags & AFPVOL_TM)) { + char *uuid = get_vol_uuid(obj, volume->v_localname); if (!uuid) { LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID", volume->v_localname); @@ -1160,7 +1181,7 @@ static int volfile_changed(struct afp_volume_name *p) * TYPE [CREATOR] * */ -int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, struct passwd *pwent) +static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, struct passwd *pwent) { FILE *fp; char path[MAXPATHLEN + 1]; @@ -1173,6 +1194,7 @@ int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, str int i; struct passwd *pw; struct vol_option save_options[VOLOPT_NUM]; + struct vol_option default_options[VOLOPT_NUM]; struct vol_option options[VOLOPT_NUM]; struct stat st; @@ -1197,14 +1219,36 @@ int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, str p1->mtime = st.st_mtime; } - memset(save_options, 0, sizeof(save_options)); + /* try putting a read lock on the volume file twice, sleep 1 second if first attempt fails */ + int retries = 2; + while (1) { + if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) { + retries--; + if (!retries) { + LOG(log_error, logtype_afpd, "readvolfile: can't lock volume file \"%s\"", path); + if ( fclose( fp ) != 0 ) { + LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) ); + } + return -1; + } + sleep(1); + continue; + } + break; + } + + memset(default_options, 0, sizeof(default_options)); /* Enable some default options for all volumes */ - save_options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE; - save_options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AUTO; + default_options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE; +#ifdef HAVE_ACLS + default_options[VOLOPT_FLAGS].i_value |= AFPVOL_ACLS; +#endif + default_options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AUTO; LOG(log_maxdebug, logtype_afpd, "readvolfile: seeding default umask: %04o", obj->options.umask); - save_options[VOLOPT_UMASK].i_value = obj->options.umask; + default_options[VOLOPT_UMASK].i_value = obj->options.umask; + memcpy(save_options, default_options, sizeof(options)); LOG(log_debug, logtype_afpd, "readvolfile: \"%s\"", path); @@ -1219,12 +1263,14 @@ int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, str case ':': /* change the default options for this file */ if (strncmp(path, VOLOPT_DEFAULT, VOLOPT_DEFAULT_LEN) == 0) { + volfree(default_options, save_options); + memcpy(default_options, save_options, sizeof(options)); *tmp = '\0'; for (i = 0; i < VOLOPT_NUM; i++) { if (parseline( sizeof( path ) - VOLOPT_DEFAULT_LEN - 1, path + VOLOPT_DEFAULT_LEN) < 0) break; - volset(save_options, NULL, tmp, sizeof(tmp) - 1, + volset(default_options, NULL, tmp, sizeof(tmp) - 1, path + VOLOPT_DEFAULT_LEN); } } @@ -1263,7 +1309,7 @@ int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, str * able to specify things in any order, but i don't want to * re-write everything. */ - memcpy(options, save_options, sizeof(options)); + memcpy(options, default_options, sizeof(options)); *volname = '\0'; /* read in up to VOLOP_NUM possible options */ @@ -1271,7 +1317,7 @@ int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, str if (parseline( sizeof( tmp ) - 1, tmp ) < 0) break; - volset(options, save_options, volname, sizeof(volname) - 1, tmp); + volset(options, default_options, volname, sizeof(volname) - 1, tmp); } /* check allow/deny lists (if not afpd master loading volumes for Zeroconf reg.): @@ -1302,7 +1348,7 @@ int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, str creatvol(obj, pwent, path, tmp, options, p2 != NULL); } - volfree(options, save_options); + volfree(options, default_options); break; case '.' : @@ -1403,6 +1449,154 @@ static void volume_unlink(struct vol *volume) } } } +/*! + * Read band-size info from Info.plist XML file of an TM sparsebundle + * + * @param path (r) path to Info.plist file + * @return band-size in bytes, -1 on error + */ +static long long int get_tm_bandsize(const char *path) +{ + EC_INIT; + FILE *file = NULL; + char buf[512]; + long long int bandsize = -1; + + EC_NULL_LOGSTR( file = fopen(path, "r"), + "get_tm_bandsize(\"%s\"): %s", + path, strerror(errno) ); + + while (fgets(buf, sizeof(buf), file) != NULL) { + if (strstr(buf, "band-size") == NULL) + continue; + + if (fscanf(file, " %lld", &bandsize) != 1) { + LOG(log_error, logtype_afpd, "get_tm_bandsize(\"%s\"): can't parse band-size", path); + EC_FAIL; + } + break; + } + +EC_CLEANUP: + if (file) + fclose(file); + LOG(log_debug, logtype_afpd, "get_tm_bandsize(\"%s\"): bandsize: %lld", path, bandsize); + return bandsize; +} + +/*! + * Return number on entries in a directory + * + * @param path (r) path to dir + * @return number of entries, -1 on error + */ +static long long int get_tm_bands(const char *path) +{ + EC_INIT; + long long int count = 0; + DIR *dir = NULL; + const struct dirent *entry; + + EC_NULL( dir = opendir(path) ); + + while ((entry = readdir(dir)) != NULL) + count++; + count -= 2; /* All OSens I'm aware of return "." and "..", so just substract them, avoiding string comparison in loop */ + +EC_CLEANUP: + if (dir) + closedir(dir); + if (ret != 0) + return -1; + return count; +} + +/*! + * Calculate used size of a TimeMachine volume + * + * This assumes that the volume is used only for TimeMachine. + * + * 1) readdir(path of volume) + * 2) for every element that matches regex "\(.*\)\.sparsebundle$" : + * 3) parse "\1.sparsebundle/Info.plist" and read the band-size XML key integer value + * 4) readdir "\1.sparsebundle/bands/" counting files + * 5) calculate used size as: (file_count - 1) * band-size + * + * The result of the calculation is returned in "volume->v_tm_used". + * "volume->v_appended" gets reset to 0. + * "volume->v_tm_cachetime" is updated with the current time from time(NULL). + * + * "volume->v_tm_used" is cached for TM_USED_CACHETIME seconds and updated by + * "volume->v_appended". The latter is increased by X every time the client + * appends X bytes to a file (in fork.c). + * + * @param vol (rw) volume to calculate + * @return 0 on success, -1 on error + */ +#define TM_USED_CACHETIME 60 /* cache for 60 seconds */ +static int get_tm_used(struct vol * restrict vol) +{ + EC_INIT; + long long int bandsize; + VolSpace used = 0; + bstring infoplist = NULL; + bstring bandsdir = NULL; + DIR *dir = NULL; + const struct dirent *entry; + const char *p; + struct stat st; + long int links; + time_t now = time(NULL); + + if (vol->v_tm_cachetime + && ((vol->v_tm_cachetime + TM_USED_CACHETIME) >= now)) { + if (vol->v_tm_used == -1) + EC_FAIL; + vol->v_tm_used += vol->v_appended; + vol->v_appended = 0; + LOG(log_debug, logtype_afpd, "getused(\"%s\"): cached: %" PRIu64 " bytes", + vol->v_path, vol->v_tm_used); + return 0; + } + + vol->v_tm_cachetime = now; + + EC_NULL( dir = opendir(vol->v_path) ); + + while ((entry = readdir(dir)) != NULL) { + if (((p = strstr(entry->d_name, "sparsebundle")) != NULL) + && (strlen(entry->d_name) == (p + strlen("sparsebundle") - entry->d_name))) { + + EC_NULL_LOG( infoplist = bformat("%s/%s/%s", vol->v_path, entry->d_name, "Info.plist") ); + + if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1) + continue; + + EC_NULL_LOG( bandsdir = bformat("%s/%s/%s/", vol->v_path, entry->d_name, "bands") ); + + if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1) + continue; + + used += (links - 1) * bandsize; + LOG(log_debug, logtype_afpd, "getused(\"%s\"): bands: %" PRIu64 " bytes", + cfrombstr(bandsdir), used); + } + } + + vol->v_tm_used = used; + +EC_CLEANUP: + if (infoplist) + bdestroy(infoplist); + if (bandsdir) + bdestroy(bandsdir); + if (dir) + closedir(dir); + + LOG(log_debug, logtype_afpd, "getused(\"%s\"): %" PRIu64 " bytes", vol->v_path, vol->v_tm_used); + + EC_EXIT; +} static int getvolspace(struct vol *vol, u_int32_t *bfree, u_int32_t *btotal, @@ -1410,6 +1604,7 @@ static int getvolspace(struct vol *vol, { int spaceflag, rc; u_int32_t maxsize; + VolSpace used; #ifndef NO_QUOTA_SUPPORT VolSpace qfree, qtotal; #endif @@ -1433,13 +1628,12 @@ static int getvolspace(struct vol *vol, return( rc ); } -#define min(a,b) ((a)<(b)?(a):(b)) #ifndef NO_QUOTA_SUPPORT if ( spaceflag == AFPVOL_NONE || spaceflag == AFPVOL_UQUOTA ) { if ( uquota_getvolspace( vol, &qfree, &qtotal, *bsize ) == AFP_OK ) { vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_UQUOTA; - *xbfree = min(*xbfree, qfree); - *xbtotal = min( *xbtotal, qtotal); + *xbfree = MIN(*xbfree, qfree); + *xbtotal = MIN(*xbtotal, qtotal); goto getvolspace_done; } } @@ -1448,50 +1642,36 @@ static int getvolspace(struct vol *vol, getvolspace_done: if (vol->v_limitsize) { - bstring cmdstr; - if ((cmdstr = bformat("du -sh \"%s\" 2> /dev/null | cut -f1", vol->v_path)) == NULL) - return AFPERR_MISC; - - FILE *cmd = popen(cfrombstr(cmdstr), "r"); - bdestroy(cmdstr); - if (cmd == NULL) + if (get_tm_used(vol) != 0) return AFPERR_MISC; - char buf[100]; - fgets(buf, 100, cmd); + *xbtotal = MIN(*xbtotal, (vol->v_limitsize * 1024 * 1024)); + *xbfree = MIN(*xbfree, *xbtotal < vol->v_tm_used ? 0 : *xbtotal - vol->v_tm_used); - if (pclose(cmd) == -1) - return AFPERR_MISC; + LOG(log_debug, logtype_afpd, + "volparams: total: %" PRIu64 ", used: %" PRIu64 ", free: %" PRIu64 " bytes", + *xbtotal, vol->v_tm_used, *xbfree); + } - size_t multi = 0; - if (buf[strlen(buf) - 2] == 'G' || buf[strlen(buf) - 2] == 'g') - /* GB */ - multi = 1024 * 1024 * 1024; - else if (buf[strlen(buf) - 2] == 'M' || buf[strlen(buf) - 2] == 'm') - /* MB */ - multi = 1024 * 1024; - else if (buf[strlen(buf) - 2] == 'K' || buf[strlen(buf) - 2] == 'k') - /* MB */ - multi = 1024; + *bfree = MIN(*xbfree, maxsize); + *btotal = MIN(*xbtotal, maxsize); + return( AFP_OK ); +} - char *p; - if (p = strchr(buf, ',')) - /* ignore fraction */ - *p = 0; - else - /* remove G|M|K char */ - buf[strlen(buf) - 2] = 0; - /* now buf contains only digits */ - long long used = atoll(buf) * multi; - LOG(log_debug, logtype_afpd, "volparams: used on volume: %llu bytes", used); +#define FCE_TM_DELTA 10 /* send notification every 10 seconds */ +void vol_fce_tm_event(void) +{ + static time_t last; + time_t now = time(NULL); + struct vol *vol = Volumes; - *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024)); - *xbfree = min(*xbfree, *xbtotal < used ? 0 : *xbtotal - used); + if ((last + FCE_TM_DELTA) < now) { + last = now; + for ( ; vol; vol = vol->v_next ) { + if (vol->v_flags & AFPVOL_TM) + (void)fce_register_tm_size(vol->v_path, vol->v_tm_used + vol->v_appended); + } } - - *bfree = min( *xbfree, maxsize); - *btotal = min( *xbtotal, maxsize); - return( AFP_OK ); } /* ----------------------- @@ -1604,7 +1784,8 @@ static int getvolparams( u_int16_t bitmap, struct vol *vol, struct stat *st, cha ashort |= VOLPBIT_ATTR_UNIXPRIV; if (vol->v_flags & AFPVOL_TM) ashort |= VOLPBIT_ATTR_TM; - + if (vol->v_flags & AFPVOL_NONETIDS) + ashort |= VOLPBIT_ATTR_NONETIDS; if (afp_version >= 32) { if (vol->v_vfs_ea) ashort |= VOLPBIT_ATTR_EXT_ATTRS; @@ -1852,7 +2033,7 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf if (!S_ISDIR(st.st_mode)) { continue; /* not a dir */ } - accessmode(volume->v_path, &ma, NULL, &st); + accessmode(volume, volume->v_path, &ma, NULL, &st); if ((ma.ma_user & (AR_UREAD | AR_USEARCH)) != (AR_UREAD | AR_USEARCH)) { continue; /* no r-x access */ } @@ -2022,7 +2203,7 @@ static void check_ea_sys_support(struct vol *vol) if (vol->v_vfs_ea == AFPVOL_EA_AUTO) { if ((vol->v_flags & AFPVOL_RO) == AFPVOL_RO) { - LOG(log_info, logtype_logger, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname); + LOG(log_info, logtype_afpd, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname); vol->v_vfs_ea = AFPVOL_EA_NONE; return; } @@ -2032,7 +2213,7 @@ static void check_ea_sys_support(struct vol *vol) process_uid = geteuid(); if (process_uid) if (seteuid(0) == -1) { - LOG(log_error, logtype_logger, "check_ea_sys_support: can't seteuid(0): %s", strerror(errno)); + LOG(log_error, logtype_afpd, "check_ea_sys_support: can't seteuid(0): %s", strerror(errno)); exit(EXITERR_SYS); } @@ -2047,7 +2228,7 @@ static void check_ea_sys_support(struct vol *vol) if (process_uid) { if (seteuid(process_uid) == -1) { - LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno)); + LOG(log_error, logtype_afpd, "can't seteuid back %s", strerror(errno)); exit(EXITERR_SYS); } } @@ -2220,7 +2401,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t DIRDID_ROOT_PARENT, DIRDID_ROOT, bfromcstr(volume->v_path), - st.st_ctime) + &st) ) == NULL) { free(vol_mname); LOG(log_error, logtype_afpd, "afp_openvol(%s): malloc: %s", volume->v_path, strerror(errno) ); @@ -2239,14 +2420,13 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t } ret = stat_vol(bitmap, volume, rbuf, rbuflen); + if (ret == AFP_OK) { + handle_special_folders(volume); + savevolinfo(volume, + volume->v_cnidserver ? volume->v_cnidserver : Cnid_srv, + volume->v_cnidport ? volume->v_cnidport : Cnid_port); - if (!(volume->v_flags & AFPVOL_RO)) { - handle_special_folders( volume ); - savevolinfo(volume, - volume->v_cnidserver ? volume->v_cnidserver : Cnid_srv, - volume->v_cnidport ? volume->v_cnidport : Cnid_port); - } /* * If you mount a volume twice, the second time the trash appears on @@ -2468,12 +2648,6 @@ void setvoltime(AFPObj *obj, struct vol *vol) { struct timeval tv; - /* just looking at vol->v_mtime is broken seriously since updates - * from other users afpd processes never are seen. - * This is not the most elegant solution (a shared memory between - * the afpd processes would come closer) - * [RS] */ - if ( gettimeofday( &tv, NULL ) < 0 ) { LOG(log_error, logtype_afpd, "setvoltime(%s): gettimeofday: %s", vol->v_path, strerror(errno) ); return; @@ -2671,13 +2845,25 @@ static int create_special_folder (const struct vol *vol, const struct _special_f static void handle_special_folders (const struct vol * vol) { const _special_folder *p = &special_folders[0]; + uid_t process_uid; - if ((vol->v_flags & AFPVOL_RO)) - return; + process_uid = geteuid(); + if (process_uid) { + if (seteuid(0) == -1) { + process_uid = 0; + } + } for (; p->name != NULL; p++) { create_special_folder (vol, p); } + + if (process_uid) { + if (seteuid(process_uid) == -1) { + LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno)); + exit(EXITERR_SYS); + } + } } const struct vol *getvolumes(void) @@ -2698,7 +2884,7 @@ void unload_volumes_and_extmap(void) * * Returns pointer to allocated storage on success, NULL on error. */ -char *get_uuid(const AFPObj *obj, const char *volname) +static char *get_vol_uuid(const AFPObj *obj, const char *volname) { char *volname_conf; char buf[1024], uuid[UUID_PRINTABLE_STRING_LENGTH], *p; @@ -2786,5 +2972,5 @@ char *get_uuid(const AFPObj *obj, const char *volname) fprintf(fp, "\"%s\"\t%36s\n", volname, cp); fclose(fp); - return strdup(uuid); + return strdup(cp); }