#include <atalk/iniparser.h>
#include <atalk/unix.h>
#include <atalk/netatalk_conf.h>
+#include <atalk/server_ipc.h>
#ifdef CNID_DB
#include <atalk/cnid.h>
DIR *dir = NULL;
const struct dirent *entry;
const char *p;
- struct stat st;
long int links;
time_t now = time(NULL);
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",
{
int spaceflag, rc;
uint32_t maxsize;
- VolSpace used;
#ifndef NO_QUOTA_SUPPORT
VolSpace qfree, qtotal;
#endif
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
* .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 ) {
}
/* 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;
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;
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;
*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 );
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);
-
- 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_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 */
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) {
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
*/
{
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;
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 ) {
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;
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,
ret = AFPERR_MISC;
goto openvol_err;
}
- free(vol_mname);
volume->v_root = dir;
curdir = dir;
* 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) {
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 );
}
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;
if (vol->v_root_postexec) {
afprun(1, vol->v_root_postexec, NULL);
}
-
- volume_free(vol);
- volume_unlink(vol);
- free(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;
}
(void)chdir("/");
- closevol(vol);
+ curdir = NULL;
+ closevol(obj, vol);
+ server_ipc_volumes(obj);
return( AFP_OK );
}