#include <atalk/adouble.h>
#include <atalk/afp.h>
#include <atalk/util.h>
-#include <atalk/volinfo.h>
#include <atalk/logger.h>
#include <atalk/vfs.h>
#include <atalk/uuid.h>
extern int afprun(int root, char *cmd, int *outfd);
-typedef struct _special_folder {
- const char *name;
- int precreate;
- mode_t mode;
- int hide;
-} _special_folder;
-
-static const _special_folder special_folders[] = {
- {".AppleDesktop", 1, 0777, 0},
- {NULL, 0, 0, 0}};
-
-/* Forward declarations */
-static void handle_special_folders (const struct vol *);
-
-static void showvol(const ucs2_t *name)
-{
- struct vol *volume = getvolumes();
-
- for ( ; volume; volume = volume->v_next ) {
- if (volume->v_hide && !strcasecmp_w( volume->v_name, name ) ) {
- volume->v_hide = 0;
- return;
- }
- }
-}
-
-static void closevol(struct vol *vol)
-{
- if (!vol)
- return;
-
- vol->v_flags &= ~AFPVOL_OPEN;
-
- of_closevol(vol);
-
- dir_free( vol->v_root );
- vol->v_root = NULL;
- if (vol->v_cdb != NULL) {
- cnid_close(vol->v_cdb);
- vol->v_cdb = NULL;
- }
-
- if (vol->v_postexec) {
- afprun(0, vol->v_postexec, NULL);
- }
- if (vol->v_root_postexec) {
- afprun(1, vol->v_root_postexec, NULL);
- }
-
- if (vol->v_deleted) {
- showvol(vol->v_name);
- volume_free(vol);
- volume_unlink(vol);
- free(vol);
- }
-}
-
/*!
* Read band-size info from Info.plist XML file of an TM sparsebundle
*
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
spaceflag = AFPVOL_GVSMASK & vol->v_flags;
/* report up to 2GB if afp version is < 2.2 (4GB if not) */
- maxsize = (afp_version < 22) ? 0x7fffffffL : 0xffffffffL;
+ maxsize = (obj->afp_version < 22) ? 0x7fffffffL : 0xffffffffL;
#ifdef AFS
if ( spaceflag == AFPVOL_NONE || spaceflag == AFPVOL_AFSGVS ) {
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 ) {
ashort |= VOLPBIT_ATTR_RO;
}
/* prior 2.1 only VOLPBIT_ATTR_RO is defined */
- if (afp_version > 20) {
+ if (obj->afp_version > 20) {
if (vol->v_cdb != NULL && (vol->v_cdb->flags & CNID_FLAG_PERSISTENT))
ashort |= VOLPBIT_ATTR_FILEID;
ashort |= VOLPBIT_ATTR_CATSEARCH;
- if (afp_version >= 30) {
+ if (obj->afp_version >= 30) {
ashort |= VOLPBIT_ATTR_UTF8;
if (vol->v_flags & AFPVOL_UNIX_PRIV)
ashort |= VOLPBIT_ATTR_UNIXPRIV;
ashort |= VOLPBIT_ATTR_TM;
if (vol->v_flags & AFPVOL_NONETIDS)
ashort |= VOLPBIT_ATTR_NONETIDS;
- if (afp_version >= 32) {
+ if (obj->afp_version >= 32) {
if (vol->v_vfs_ea)
ashort |= VOLPBIT_ATTR_EXT_ATTRS;
if (vol->v_flags & AFPVOL_ACLS)
int vcnt;
size_t len;
- load_volumes(obj, of_closevol);
+ load_volumes(obj);
data = rbuf + 5;
for ( vcnt = 0, volume = getvolumes(); volume; volume = volume->v_next ) {
continue; /* no r-x access */
}
}
- if (volume->v_hide) {
- continue; /* config file changed but the volume was mounted */
- }
- if (utf8_encoding()) {
+ if (utf8_encoding(obj)) {
len = ucs2_to_charset_allocate(CH_UTF8_MAC, &namebuf, volume->v_u8mname);
} else {
len = ucs2_to_charset_allocate(obj->options.maccharset, &namebuf, volume->v_macname);
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);
if ( ! volume->v_cdb && ! (flags & CNID_FLAG_MEMORY)) {
/* The first attempt failed and it wasn't yet an attempt to open in-memory */
{
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 *volname_tmp;
if ((volname_tmp = strchr(volname,'+')) != NULL)
volname = volname_tmp+1;
- if (utf8_encoding()) {
+ if (utf8_encoding(obj)) {
namelen = convert_string(CH_UTF8_MAC, CH_UCS2, ibuf, len, volname, sizeof(obj->oldtmp));
} else {
namelen = convert_string(obj->options.maccharset, CH_UCS2, ibuf, len, volname, sizeof(obj->oldtmp));
if ((len + 1) & 1) /* pad to an even boundary */
ibuf++;
- load_volumes(obj, of_closevol);
+ load_volumes(obj);
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;
/* initialize volume variables
* FIXME file size
*/
- if (utf8_encoding()) {
+ if (utf8_encoding(obj)) {
volume->max_filename = UTF8FILELEN_EARLY;
}
else {
volume->v_flags |= AFPVOL_OPEN;
volume->v_cdb = NULL;
- if (utf8_encoding()) {
+ if (utf8_encoding(obj)) {
len = convert_string_allocate(CH_UCS2, CH_UTF8_MAC, volume->v_u8mname, namelen, &vol_mname);
} else {
len = convert_string_allocate(CH_UCS2, obj->options.maccharset, volume->v_macname, namelen, &vol_mname);
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;
ret = stat_vol(obj, bitmap, volume, rbuf, rbuflen);
if (ret == AFP_OK) {
- handle_special_folders(volume);
- savevolinfo(volume,
- volume->v_cnidserver ? volume->v_cnidserver : obj->options.Cnid_srv,
- volume->v_cnidport ? volume->v_cnidport : obj->options.Cnid_port);
-
-
/*
* If you mount a volume twice, the second time the trash appears on
* the desk-top. That's because the Mac remembers the DID for the
goto openvol_err;
}
}
+
+ const char *msg;
+ if ((msg = iniparser_getstring(obj->iniconfig, volume->v_configname, "login message", NULL)) != NULL)
+ setmessage(msg);
+
+ free(vol_mname);
return( AFP_OK );
}
cnid_close(volume->v_cdb);
volume->v_cdb = NULL;
}
+ free(vol_mname);
*rbuflen = 0;
return ret;
}
+void closevol(const AFPObj *obj, struct vol *vol)
+{
+ if (!vol)
+ return;
+
+ vol->v_flags &= ~AFPVOL_OPEN;
+
+ of_closevol(obj, vol);
+
+ dir_free( vol->v_root );
+ vol->v_root = NULL;
+ if (vol->v_cdb != NULL) {
+ cnid_close(vol->v_cdb);
+ vol->v_cdb = NULL;
+ }
+
+ if (vol->v_postexec) {
+ afprun(0, vol->v_postexec, NULL);
+ }
+ if (vol->v_root_postexec) {
+ afprun(1, vol->v_root_postexec, NULL);
+ }
+}
+
/* ------------------------- */
-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);
return( AFP_OK );
}
struct timeval tv;
struct stat st;
- if (!(afp_version > 21 && obj->options.flags & OPTION_SERVERNOTIF))
+ if (!(obj->afp_version > 21 && obj->options.flags & OPTION_SERVERNOTIF))
return 0;
if ( gettimeofday( &tv, NULL ) < 0 )
/* or finder doesn't update free space
* AFP 3.2 and above clients seem to be ok without so many notification
*/
- if (afp_version < 32 && obj->options.flags & OPTION_SERVERNOTIF) {
+ if (obj->afp_version < 32 && obj->options.flags & OPTION_SERVERNOTIF) {
obj->attention(obj->dsi, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED);
}
}
ad_close(&ad, ADFLAGS_HF);
return( AFP_OK );
}
-
-/*
- * precreate a folder
- * this is only intended for folders in the volume root
- * It will *not* work if the folder name contains extended characters
- */
-static int create_special_folder (const struct vol *vol, const struct _special_folder *folder)
-{
- char *p,*q,*r;
- struct adouble ad;
- uint16_t attr;
- struct stat st;
- int ret;
-
-
- p = (char *) malloc ( strlen(vol->v_path)+strlen(folder->name)+2);
- if ( p == NULL) {
- LOG(log_error, logtype_afpd,"malloc failed");
- exit (EXITERR_SYS);
- }
-
- q=strdup(folder->name);
- if ( q == NULL) {
- LOG(log_error, logtype_afpd,"malloc failed");
- exit (EXITERR_SYS);
- }
-
- strcpy(p, vol->v_path);
- strcat(p, "/");
-
- r=q;
- while (*r) {
- if ((vol->v_casefold & AFPVOL_MTOUUPPER))
- *r=toupper(*r);
- else if ((vol->v_casefold & AFPVOL_MTOULOWER))
- *r=tolower(*r);
- r++;
- }
- strcat(p, q);
-
- if ( (ret = stat( p, &st )) < 0 ) {
- if (folder->precreate) {
- if (ad_mkdir(p, folder->mode)) {
- LOG(log_debug, logtype_afpd,"Creating '%s' failed in %s: %s", p, vol->v_path, strerror(errno));
- free(p);
- free(q);
- return -1;
- }
- ret = 0;
- }
- }
-
- if ( !ret && folder->hide) {
- /* Hide it */
- ad_init(&ad, vol);
- if (ad_open(&ad, p, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0) {
- free(p);
- free(q);
- return (-1);
- }
-
- ad_setname(&ad, folder->name);
-
- ad_getattr(&ad, &attr);
- attr |= htons( ntohs( attr ) | ATTRBIT_INVISIBLE );
- ad_setattr(&ad, attr);
-
- /* do the same with the finder info */
- if (ad_entry(&ad, ADEID_FINDERI)) {
- memcpy(&attr, ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF, sizeof(attr));
- attr |= htons(FINDERINFO_INVISIBLE);
- memcpy(ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF,&attr, sizeof(attr));
- }
-
- ad_flush(&ad);
- ad_close(&ad, ADFLAGS_HF);
- }
- free(p);
- free(q);
- return 0;
-}
-
-static void handle_special_folders (const struct vol * vol)
-{
- const _special_folder *p = &special_folders[0];
-
- become_root();
-
- for (; p->name != NULL; p++) {
- create_special_folder (vol, p);
- }
-
- unbecome_root();
-}