X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?p=netatalk.git;a=blobdiff_plain;f=etc%2Fafpd%2Fvolume.c;h=7bdff75dff53ecf87007a9b001a45c87bae944de;hp=61d744ca70cdc980d21b98734a06b25682e3e1d9;hb=5eb3b5ac51c8221009041928a5a08c101d2be743;hpb=8fed5c3721b742930a3789f58c104d2a7a234dcf diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index 61d744ca..7bdff75d 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 @@ -381,7 +369,7 @@ static int getvolparams(const AFPObj *obj, uint16_t bitmap, struct vol *vol, str } /* prior 2.1 only VOLPBIT_ATTR_RO is defined */ if (obj->afp_version > 20) { - if (vol->v_cdb != NULL && (vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) + if (vol->v_cdb != NULL && (vol->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) ashort |= VOLPBIT_ATTR_FILEID; ashort |= VOLPBIT_ATTR_CATSEARCH; @@ -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,14 +639,7 @@ static int volume_openDB(const AFPObj *obj, struct vol *volume) flags |= CNID_FLAG_NODEV; } - 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_cnidport); + volume->v_cdb = cnid_open(volume, volume->v_cnidscheme, flags); if ( ! volume->v_cdb && ! (flags & CNID_FLAG_MEMORY)) { /* The first attempt failed and it wasn't yet an attempt to open in-memory */ @@ -657,7 +648,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, "tdb", flags); #ifdef SERVERTEXT /* kill ourself with SIGUSR2 aka msg pending */ if (volume->v_cdb) { @@ -672,6 +663,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 */ @@ -679,16 +695,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; @@ -721,7 +735,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 ) { @@ -765,33 +779,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; @@ -820,9 +807,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, @@ -838,7 +825,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; @@ -860,7 +846,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t * fixing the trash at DID 17. * FIXME (RL): should it be done inside a CNID backend ? (always returning Trash DID when asked) ? */ - if ((volume->v_cdb->flags & CNID_FLAG_PERSISTENT)) { + if ((volume->v_cdb->cnid_db_flags & CNID_FLAG_PERSISTENT)) { /* FIXME find db time stamp */ if (cnid_getstamp(volume->v_cdb, volume->v_stamp, sizeof(volume->v_stamp)) < 0) { @@ -871,6 +857,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 ); } @@ -885,18 +878,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; @@ -914,20 +908,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; @@ -941,7 +935,8 @@ int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_ (void)chdir("/"); curdir = NULL; - closevol(vol); + closevol(obj, vol); + server_ipc_volumes(obj); return( AFP_OK ); }