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=8798635a07678150921e3b5139f54ec942269b73;hb=5eb3b5ac51c8221009041928a5a08c101d2be743;hpb=1ae3c8a1f36c4f9d2a5272a0e700463817aaff1b diff --git a/etc/afpd/volume.c b/etc/afpd/volume.c index 8798635a..7bdff75d 100644 --- a/etc/afpd/volume.c +++ b/etc/afpd/volume.c @@ -39,6 +39,7 @@ #include #include #include +#include #ifdef CNID_DB #include @@ -176,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", @@ -363,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; @@ -524,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); + 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; @@ -555,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; @@ -569,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 ); @@ -623,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 */ @@ -639,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) { @@ -654,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 */ @@ -668,7 +702,7 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t size_t namelen; uint16_t bitmap; char *vol_uname; - char *vol_mname; + char *vol_mname = NULL; char *volname_tmp; ibuf += 2; @@ -701,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); + load_volumes(obj, lv_none); for ( volume = getvolumes(); volume; volume = volume->v_next ) { if ( strcasecmp_w( (ucs2_t*) volname, volume->v_name ) == 0 ) { @@ -812,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) { @@ -825,10 +859,11 @@ int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t } const char *msg; - if ((msg = iniparser_getstring(obj->iniconfig, volume->v_configname, "login message", NULL)) != NULL) + 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 ); } @@ -901,6 +936,7 @@ int afp_closevol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, si (void)chdir("/"); curdir = NULL; closevol(obj, vol); + server_ipc_volumes(obj); return( AFP_OK ); }