X-Git-Url: https://arthur.barton.de/gitweb/?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Fvolume.c;h=a3ee79278763d198029af7c35a0be3260cae17a2;hp=1adf24af522a22efeda7abdf8e0e40a28b599187;hb=980548c882a297d26e67397d0f72e0b991f36bf2;hpb=adf65f7eb3083f0e2f77fb04f540c233b99f7b77 diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index 1adf24af..a3ee7927 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CNID_DB #include @@ -152,7 +153,6 @@ static int get_tm_used(struct vol * restrict vol) DIR *dir = NULL; const struct dirent *entry; const char *p; - struct stat st; long int links; time_t now = time(NULL); @@ -177,13 +177,18 @@ static int get_tm_used(struct vol * restrict vol) EC_NULL_LOG( infoplist = bformat("%s/%s/%s", vol->v_path, entry->d_name, "Info.plist") ); - if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1) + if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1) { + bdestroy(infoplist); continue; + } EC_NULL_LOG( bandsdir = bformat("%s/%s/%s/", vol->v_path, entry->d_name, "bands") ); - if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1) + if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1) { + bdestroy(infoplist); + bdestroy(bandsdir); continue; + } used += (links - 1) * bandsize; LOG(log_debug, logtype_afpd, "getused(\"%s\"): bands: %" PRIu64 " bytes", @@ -212,7 +217,6 @@ static int getvolspace(const AFPObj *obj, struct vol *vol, { int spaceflag, rc; uint32_t maxsize; - VolSpace used; #ifndef NO_QUOTA_SUPPORT VolSpace qfree, qtotal; #endif @@ -264,22 +268,6 @@ getvolspace_done: return( AFP_OK ); } -#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 = getvolumes(); - - 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); - } - } -} - /* ----------------------- * set volume creation date * avoid duplicate, well at least it tries @@ -321,7 +309,7 @@ static int getvolparams(const AFPObj *obj, uint16_t bitmap, struct vol *vol, str * .Parent file here if it doesn't exist. */ /* Convert adouble:v2 to adouble:ea on the fly */ - (void)ad_convert(vol->v_path, st, vol); + (void)ad_convert(vol->v_path, st, vol, NULL); ad_init(&ad, vol); if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0 ) { @@ -542,11 +530,12 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf char *namebuf; int vcnt; size_t len; + uint32_t aint; - load_volumes(obj, closevol); + load_volumes(obj, lv_none); data = rbuf + 5; - for ( vcnt = 0, volume = getvolumes(); volume; volume = volume->v_next ) { + for ( vcnt = 0, volume = getvolumes(); volume && vcnt < 255; volume = volume->v_next ) { if (!(volume->v_flags & AFPVOL_NOSTAT)) { struct maccess ma; @@ -573,6 +562,14 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf if (len == (size_t)-1) continue; + /* + * There seems to be an undocumented limit on how big our reply can get + * before the client chokes and closes the connection. + * Testing with 10.8.4 found the limit at ~4600 bytes. Go figure. + */ + if (((data + len + 3) - rbuf) > 4600) + break; + /* set password bit if there's a volume password */ *data = (volume->v_password) ? AFPSRVR_PASSWD : 0; @@ -587,12 +584,13 @@ int afp_getsrvrparms(AFPObj *obj, char *ibuf _U_, size_t ibuflen _U_, char *rbuf *rbuflen = data - rbuf; data = rbuf; if ( gettimeofday( &tv, NULL ) < 0 ) { - LOG(log_error, logtype_afpd, "afp_getsrvrparms(%s): gettimeofday: %s", volume->v_path, strerror(errno) ); + LOG(log_error, logtype_afpd, "afp_getsrvrparms: gettimeofday: %s", strerror(errno) ); *rbuflen = 0; return AFPERR_PARAM; } - tv.tv_sec = AD_DATE_FROM_UNIX(tv.tv_sec); - memcpy(data, &tv.tv_sec, sizeof( uint32_t)); + + aint = AD_DATE_FROM_UNIX(tv.tv_sec); + memcpy(data, &aint, sizeof( uint32_t)); data += sizeof( uint32_t); *data = vcnt; return( AFP_OK ); @@ -641,22 +639,16 @@ static int volume_openDB(const AFPObj *obj, struct vol *volume) flags |= CNID_FLAG_NODEV; } - if (volume->v_cnidscheme == NULL) { - volume->v_cnidscheme = strdup(DEFAULT_CNID_SCHEME); - LOG(log_info, logtype_afpd, "Volume %s use CNID scheme %s.", - volume->v_path, volume->v_cnidscheme); - } - - LOG(log_info, logtype_afpd, "CNID server: %s:%s", - volume->v_cnidserver ? volume->v_cnidserver : obj->options.Cnid_srv, - volume->v_cnidport ? volume->v_cnidport : obj->options.Cnid_port); + LOG(log_debug, logtype_afpd, "CNID server: %s:%s", volume->v_cnidserver, volume->v_cnidport); volume->v_cdb = cnid_open(volume->v_path, volume->v_umask, volume->v_cnidscheme, flags, - volume->v_cnidserver ? volume->v_cnidserver : obj->options.Cnid_srv, - volume->v_cnidport ? volume->v_cnidport : obj->options.Cnid_port); + volume->v_cnidserver, + volume->v_cnidport, + (const void *)obj, + volume->v_uuid); if ( ! volume->v_cdb && ! (flags & CNID_FLAG_MEMORY)) { /* The first attempt failed and it wasn't yet an attempt to open in-memory */ @@ -665,7 +657,7 @@ static int volume_openDB(const AFPObj *obj, struct vol *volume) LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.", volume->v_path); flags |= CNID_FLAG_MEMORY; - volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, "tdb", flags, NULL, NULL); + volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, "tdb", flags, NULL, NULL, NULL, NULL); #ifdef SERVERTEXT /* kill ourself with SIGUSR2 aka msg pending */ if (volume->v_cdb) { @@ -680,6 +672,31 @@ static int volume_openDB(const AFPObj *obj, struct vol *volume) return (!volume->v_cdb)?-1:0; } +/* + * Send list of open volumes to afpd master via IPC + */ +static void server_ipc_volumes(AFPObj *obj) +{ + struct vol *volume, *vols; + volume = vols = getvolumes(); + bstring openvolnames = bfromcstr(""); + bool firstvol = true; + + while (volume) { + if (volume->v_flags & AFPVOL_OPEN) { + if (!firstvol) + bcatcstr(openvolnames, ", "); + else + firstvol = false; + bcatcstr(openvolnames, volume->v_localname); + } + volume = volume->v_next; + } + + ipc_child_write(obj->ipc_fd, IPC_VOLUMES, blength(openvolnames), bdata(openvolnames)); + bdestroy(openvolnames); +} + /* ------------------------- * we are the user here */ @@ -687,16 +704,14 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t { struct stat st; char *volname; - char *p; struct vol *volume; struct dir *dir; int len, ret; size_t namelen; uint16_t bitmap; - char path[ MAXPATHLEN + 1]; char *vol_uname; - char *vol_mname; + char *vol_mname = NULL; char *volname_tmp; ibuf += 2; @@ -729,7 +744,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t if ((len + 1) & 1) /* pad to an even boundary */ ibuf++; - load_volumes(obj, closevol); + load_volumes(obj, lv_none); for ( volume = getvolumes(); volume; volume = volume->v_next ) { if ( strcasecmp_w( (ucs2_t*) volname, volume->v_name ) == 0 ) { @@ -773,33 +788,6 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t return AFPERR_PARAM; } - if ( NULL == getcwd(path, MAXPATHLEN)) { - /* shouldn't be fatal but it will fail later */ - LOG(log_error, logtype_afpd, "afp_openvol(%s): volume pathlen too long", volume->v_path); - return AFPERR_MISC; - } - - /* Normalize volume path */ -#ifdef REALPATH_TAKES_NULL - if ((volume->v_path = realpath(path, NULL)) == NULL) - return AFPERR_MISC; -#else - if ((volume->v_path = malloc(MAXPATHLEN+1)) == NULL) - return AFPERR_MISC; - if (realpath(path, volume->v_path) == NULL) { - free(volume->v_path); - return AFPERR_MISC; - } - /* Safe some memory */ - char *tmp; - if ((tmp = strdup(volume->v_path)) == NULL) { - free(volume->v_path); - return AFPERR_MISC; - } - free(volume->v_path); - volume->v_path = tmp; -#endif - if (volume_codepage(obj, volume) < 0) { ret = AFPERR_MISC; goto openvol_err; @@ -828,9 +816,9 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t goto openvol_err; } - if ((vol_uname = strrchr(path, '/')) == NULL) - vol_uname = path; - else if (*(vol_uname + 1) != '\0') + if ((vol_uname = strrchr(volume->v_path, '/')) == NULL) + vol_uname = volume->v_path; + else if (vol_uname[1] != '\0') vol_uname++; if ((dir = dir_new(vol_mname, @@ -846,7 +834,6 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t ret = AFPERR_MISC; goto openvol_err; } - free(vol_mname); volume->v_root = dir; curdir = dir; @@ -879,6 +866,13 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t goto openvol_err; } } + + const char *msg; + if ((msg = atalk_iniparser_getstring(obj->iniconfig, volume->v_configname, "login message", NULL)) != NULL) + setmessage(msg); + + free(vol_mname); + server_ipc_volumes(obj); return( AFP_OK ); } @@ -893,18 +887,19 @@ openvol_err: cnid_close(volume->v_cdb); volume->v_cdb = NULL; } + free(vol_mname); *rbuflen = 0; return ret; } -void closevol(struct vol *vol) +void closevol(const AFPObj *obj, struct vol *vol) { if (!vol) return; vol->v_flags &= ~AFPVOL_OPEN; - of_closevol(vol); + of_closevol(obj, vol); dir_free( vol->v_root ); vol->v_root = NULL; @@ -922,20 +917,20 @@ void closevol(struct vol *vol) } /* ------------------------- */ -void close_all_vol(void) +void close_all_vol(const AFPObj *obj) { struct vol *ovol; curdir = NULL; for ( ovol = getvolumes(); ovol; ovol = ovol->v_next ) { if ( (ovol->v_flags & AFPVOL_OPEN) ) { ovol->v_flags &= ~AFPVOL_OPEN; - closevol(ovol); + closevol(obj, ovol); } } } /* ------------------------- */ -int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) +int afp_closevol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) { struct vol *vol; uint16_t vid; @@ -948,7 +943,9 @@ int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ } (void)chdir("/"); - closevol(vol); + curdir = NULL; + closevol(obj, vol); + server_ipc_volumes(obj); return( AFP_OK ); }