#include <grp.h>
#include <utime.h>
#include <errno.h>
-#ifdef HAVE_STRINGS_H
-#include <strings.h>
-#endif
-/* STDC check */
-#if STDC_HEADERS
#include <string.h>
-#else /* STDC_HEADERS */
-#ifndef HAVE_STRCHR
-#define strchr index
-#define strrchr index
-#endif /* HAVE_STRCHR */
-char *strchr (), *strrchr ();
-#ifndef HAVE_MEMCPY
-#define memcpy(d,s,n) bcopy ((s), (d), (n))
-#define memmove(d,s,n) bcopy ((s), (d), (n))
-#endif /* ! HAVE_MEMCPY */
-#endif /* STDC_HEADERS */
#include <sys/param.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <inttypes.h>
#include <time.h>
-#include <atalk/asp.h>
#include <atalk/dsi.h>
#include <atalk/adouble.h>
#include <atalk/afp.h>
#include <atalk/logger.h>
#include <atalk/vfs.h>
#include <atalk/uuid.h>
+#include <atalk/ea.h>
#include <atalk/bstrlib.h>
#include <atalk/bstradd.h>
#include <atalk/ftw.h>
#include <atalk/globals.h>
#include <atalk/fce_api.h>
#include <atalk/errchk.h>
+#include <atalk/iniparser.h>
#ifdef CNID_DB
#include <atalk/cnid.h>
extern int afprun(int root, char *cmd, int *outfd);
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif /* ! MIN */
-
-#ifndef UUID_PRINTABLE_STRING_LENGTH
-#define UUID_PRINTABLE_STRING_LENGTH 37
-#endif
-
/* Globals */
struct vol *current_vol; /* last volume from getvolbyvid() */
static struct vol *Volumes = NULL;
-static u_int16_t lastvid = 0;
+static uint16_t lastvid = 0;
static char *Trash = "\02\024Network Trash Folder";
-static struct extmap *Extmap = NULL, *Defextmap = NULL;
-static int Extmap_cnt;
-static void free_extmap(void);
-
#define VOLOPT_ALLOW 0 /* user allow list */
#define VOLOPT_DENY 1 /* user deny list */
#define VOLOPT_RWLIST 2 /* user rw list */
#define VOLOPT_MACCHARSET 16
#define VOLOPT_CNIDSCHEME 17
#define VOLOPT_ADOUBLE 18 /* adouble version */
-
-#ifdef FORCE_UIDGID
-#warning UIDGID
-#include "uid.h"
-
-#define VOLOPT_FORCEUID 19 /* force uid for username x */
-#define VOLOPT_FORCEGID 20 /* force gid for group x */
-#endif /* FORCE_UIDGID */
-
+/* Usable slot: 19/20 */
#define VOLOPT_UMASK 21
#define VOLOPT_ALLOWED_HOSTS 22
#define VOLOPT_DENIED_HOSTS 23
#define VOLOPT_NUM (VOLOPT_MAX + 1)
#define VOLPASSLEN 8
-#define VOLOPT_DEFAULT ":DEFAULT:"
-#define VOLOPT_DEFAULT_LEN 9
struct vol_option {
char *c_value;
static const _special_folder special_folders[] = {
{"Network Trash Folder", 1, 0777, 1},
- {"Temporary Items", 1, 0777, 1},
{".AppleDesktop", 1, 0777, 0},
-#if 0
- {"TheFindByContentFolder", 0, 0, 1},
- {"TheVolumeSettingsFolder", 0, 0, 1},
-#endif
{NULL, 0, 0, 0}};
/* Forward declarations */
static void volume_free(struct vol *vol);
static void check_ea_sys_support(struct vol *vol);
static char *get_vol_uuid(const AFPObj *obj, const char *volname);
-static int readvolfile(AFPObj *obj, struct afp_volume_name *p1,char *p2, int user, struct passwd *pwent);
static void volfree(struct vol_option *options, const struct vol_option *save)
{
* $s -> server name (hostname if it doesn't exist)
* $u -> username (guest is usually nobody)
* $v -> volume name or basename if null
- * $z -> zone (may not exist)
* $$ -> $
*
* This get's called from readvolfile with
} else if (is_var(p, "$c")) {
if (afpmaster && xlatevolname)
return NULL;
-#ifndef NO_DDP
- if (obj->proto == AFPPROTO_ASP) {
- ASP asp = obj->handle;
-
- len = sprintf(dest, "%u.%u", ntohs(asp->asp_sat.sat_addr.s_net),
- asp->asp_sat.sat_addr.s_node);
- dest += len;
- destlen -= len;
-
- }
-#endif
- if (obj->proto == AFPPROTO_DSI) {
- DSI *dsi = obj->handle;
- len = sprintf(dest, "%s:%u",
- getip_string((struct sockaddr *)&dsi->client),
- getip_port((struct sockaddr *)&dsi->client));
- dest += len;
- destlen -= len;
- }
+ DSI *dsi = obj->dsi;
+ len = sprintf(dest, "%s:%u",
+ getip_string((struct sockaddr *)&dsi->client),
+ getip_port((struct sockaddr *)&dsi->client));
+ dest += len;
+ destlen -= len;
} else if (is_var(p, "$d")) {
if (afpmaster && xlatevolname)
return NULL;
} else if (is_var(p, "$i")) {
if (afpmaster && xlatevolname)
return NULL;
-#ifndef NO_DDP
- if (obj->proto == AFPPROTO_ASP) {
- ASP asp = obj->handle;
- len = sprintf(dest, "%u", ntohs(asp->asp_sat.sat_addr.s_net));
- dest += len;
- destlen -= len;
-
- }
-#endif
- if (obj->proto == AFPPROTO_DSI) {
- DSI *dsi = obj->handle;
- q = getip_string((struct sockaddr *)&dsi->client);
- }
+ DSI *dsi = obj->dsi;
+ q = getip_string((struct sockaddr *)&dsi->client);
} else if (is_var(p, "$s")) {
- if (obj->Obj)
- q = obj->Obj;
- else if (obj->options.server) {
- q = obj->options.server;
- } else
- q = obj->options.hostname;
+ q = obj->options.hostname;
} else if (obj->username && is_var(p, "$u")) {
if (afpmaster && xlatevolname)
return NULL;
else if (*(q + 1) != '\0')
q++;
}
- } else if (is_var(p, "$z")) {
- q = obj->Zone;
} else if (is_var(p, "$$")) {
q = "$";
} else
return ret;
}
-/* to make sure that val is valid, make sure to select an opt that
- includes val */
-static int optionok(const char *buf, const char *opt, const char *val)
-{
- if (!strstr(buf,opt))
- return 0;
- if (!val[1])
- return 0;
- return 1;
-}
-
-
/* -------------------- */
-static void setoption(struct vol_option *options, struct vol_option *save, int opt, const char *val)
+static void setoption(struct vol_option *options, const struct vol_option *save, int opt, const char *val)
{
if (options[opt].c_value && (!save || options[opt].c_value != save[opt].c_value))
free(options[opt].c_value);
options[opt].c_value = strdup(val + 1);
}
-/* ------------------------------------------
- handle all the options. tmp can't be NULL. */
-static void volset(struct vol_option *options, struct vol_option *save,
- char *volname, int vlen,
- const char *tmp)
+/* Parse iniconfig and initalize volume options */
+static void volset(const dictionary *conf, const char *vol, struct vol_option *options, const struct vol_option *save)
{
- char *val;
+ const char *val;
+ char *p, *q;
- val = strchr(tmp, ':');
- if (!val) {
- /* we'll assume it's a volume name. */
- strncpy(volname, tmp, vlen);
- volname[vlen] = 0;
- return;
- }
-#if 0
- LOG(log_debug, logtype_afpd, "Parsing volset %s", val);
-#endif
- if (optionok(tmp, "allow:", val)) {
+ if (val = iniparser_getstring(conf, vol, "allow", NULL))
setoption(options, save, VOLOPT_ALLOW, val);
- } else if (optionok(tmp, "deny:", val)) {
+ if (val = iniparser_getstring(conf, vol, "deny", NULL))
setoption(options, save, VOLOPT_DENY, val);
- } else if (optionok(tmp, "rwlist:", val)) {
+ if (val = iniparser_getstring(conf, vol, "rwlist", NULL))
setoption(options, save, VOLOPT_RWLIST, val);
- } else if (optionok(tmp, "rolist:", val)) {
+ if (val = iniparser_getstring(conf, vol, "rolist", NULL))
setoption(options, save, VOLOPT_ROLIST, val);
- } else if (optionok(tmp, "codepage:", val)) {
- LOG (log_error, logtype_afpd, "The old codepage system has been removed. Please make sure to read the documentation !!!!");
- /* Make sure we don't screw anything */
- exit (EXITERR_CONF);
- } else if (optionok(tmp, "volcharset:", val)) {
+ if (val = iniparser_getstring(conf, vol, "volcharset", NULL))
setoption(options, save, VOLOPT_ENCODING, val);
- } else if (optionok(tmp, "maccharset:", val)) {
- setoption(options, save, VOLOPT_MACCHARSET, val);
- } else if (optionok(tmp, "veto:", val)) {
- setoption(options, save, VOLOPT_VETO, val);
- } else if (optionok(tmp, "cnidscheme:", val)) {
- setoption(options, save, VOLOPT_CNIDSCHEME, val);
- } else if (optionok(tmp, "casefold:", val)) {
- if (strcasecmp(val + 1, "tolower") == 0)
- options[VOLOPT_CASEFOLD].i_value = AFPVOL_UMLOWER;
- else if (strcasecmp(val + 1, "toupper") == 0)
- options[VOLOPT_CASEFOLD].i_value = AFPVOL_UMUPPER;
- else if (strcasecmp(val + 1, "xlatelower") == 0)
- options[VOLOPT_CASEFOLD].i_value = AFPVOL_UUPPERMLOWER;
- else if (strcasecmp(val + 1, "xlateupper") == 0)
- options[VOLOPT_CASEFOLD].i_value = AFPVOL_ULOWERMUPPER;
- } else if (optionok(tmp, "adouble:", val)) {
- if (strcasecmp(val + 1, "v1") == 0)
- options[VOLOPT_ADOUBLE].i_value = AD_VERSION1;
-#if AD_VERSION == AD_VERSION2
- else if (strcasecmp(val + 1, "v2") == 0)
- options[VOLOPT_ADOUBLE].i_value = AD_VERSION2;
- else if (strcasecmp(val + 1, "osx") == 0)
- options[VOLOPT_ADOUBLE].i_value = AD_VERSION2_OSX;
- else if (strcasecmp(val + 1, "sfm") == 0)
- options[VOLOPT_ADOUBLE].i_value = AD_VERSION1_SFM;
-#endif
- } else if (optionok(tmp, "options:", val)) {
- char *p;
-
- if ((p = strtok(val + 1, ",")) == NULL) /* nothing */
- return;
-
- while (p) {
- if (strcasecmp(p, "prodos") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_A2VOL;
- else if (strcasecmp(p, "mswindows") == 0) {
- options[VOLOPT_FLAGS].i_value |= AFPVOL_MSWINDOWS | AFPVOL_USEDOTS;
- } else if (strcasecmp(p, "crlf") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_CRLF;
- else if (strcasecmp(p, "noadouble") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_NOADOUBLE;
- else if (strcasecmp(p, "ro") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_RO;
- else if (strcasecmp(p, "nohex") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_NOHEX;
- else if (strcasecmp(p, "usedots") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_USEDOTS;
- else if (strcasecmp(p, "invisibledots") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_USEDOTS | AFPVOL_INV_DOTS;
- else if (strcasecmp(p, "limitsize") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_LIMITSIZE;
- /* support for either "dropbox" or "dropkludge" */
- else if (strcasecmp(p, "dropbox") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_DROPBOX;
- else if (strcasecmp(p, "dropkludge") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_DROPBOX;
- else if (strcasecmp(p, "nofileid") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_NOFILEID;
- else if (strcasecmp(p, "nostat") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_NOSTAT;
- else if (strcasecmp(p, "preexec_close") == 0)
- options[VOLOPT_PREEXEC].i_value = 1;
- else if (strcasecmp(p, "root_preexec_close") == 0)
- options[VOLOPT_ROOTPREEXEC].i_value = 1;
- else if (strcasecmp(p, "upriv") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_UNIX_PRIV;
- else if (strcasecmp(p, "nodev") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_NODEV;
- else if (strcasecmp(p, "caseinsensitive") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_CASEINSEN;
- else if (strcasecmp(p, "illegalseq") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_EILSEQ;
- else if (strcasecmp(p, "nocnidcache") == 0)
- options[VOLOPT_FLAGS].i_value &= ~AFPVOL_CACHE;
- else if (strcasecmp(p, "tm") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_TM;
- else if (strcasecmp(p, "searchdb") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_SEARCHDB;
- else if (strcasecmp(p, "nonetids") == 0)
- options[VOLOPT_FLAGS].i_value |= AFPVOL_NONETIDS;
- else if (strcasecmp(p, "noacls") == 0)
- options[VOLOPT_FLAGS].i_value &= ~AFPVOL_ACLS;
- p = strtok(NULL, ",");
- }
- } else if (optionok(tmp, "cnidserver:", val)) {
- setoption(options, save, VOLOPT_CNIDSERVER, val);
+ if (val = iniparser_getstring(conf, vol, "maccharset", NULL))
+ setoption(options, save, VOLOPT_MACCHARSET, val);
- char *p = strrchr(val + 1, ':');
- if (p) {
- *p = 0;
- setoption(options, save, VOLOPT_CNIDPORT, p);
- }
+ if (val = iniparser_getstring(conf, vol, "veto", NULL))
+ setoption(options, save, VOLOPT_VETO, val);
- LOG(log_debug, logtype_afpd, "CNID Server for volume '%s': %s:%s",
- volname, val + 1, p ? p + 1 : Cnid_port);
+ if (val = iniparser_getstring(conf, vol, "cnidscheme", NULL))
+ setoption(options, save, VOLOPT_CNIDSCHEME, val);
- } else if (optionok(tmp, "dbpath:", val)) {
+ if (val = iniparser_getstring(conf, vol, "dbpath", NULL))
setoption(options, save, VOLOPT_DBPATH, val);
- } else if (optionok(tmp, "umask:", val)) {
- options[VOLOPT_UMASK].i_value = (int)strtol(val +1, NULL, 8);
- } else if (optionok(tmp, "dperm:", val)) {
- options[VOLOPT_DPERM].i_value = (int)strtol(val+1, NULL, 8);
- } else if (optionok(tmp, "fperm:", val)) {
- options[VOLOPT_FPERM].i_value = (int)strtol(val+1, NULL, 8);
- } else if (optionok(tmp, "perm:", val)) {
- options[VOLOPT_DFLTPERM].i_value = (int)strtol(val+1, NULL, 8);
- } else if (optionok(tmp, "password:", val)) {
+ if (val = iniparser_getstring(conf, vol, "password", NULL))
setoption(options, save, VOLOPT_PASSWORD, val);
-#ifdef FORCE_UIDGID
-
- /* this code allows forced uid/gid per volume settings */
- } else if (optionok(tmp, "forceuid:", val)) {
- setoption(options, save, VOLOPT_FORCEUID, val);
- } else if (optionok(tmp, "forcegid:", val)) {
- setoption(options, save, VOLOPT_FORCEGID, val);
-
-#endif /* FORCE_UIDGID */
- } else if (optionok(tmp, "root_preexec:", val)) {
+ if (val = iniparser_getstring(conf, vol, "root_preexec", NULL))
setoption(options, save, VOLOPT_ROOTPREEXEC, val);
- } else if (optionok(tmp, "preexec:", val)) {
+ if (val = iniparser_getstring(conf, vol, "preexec", NULL))
setoption(options, save, VOLOPT_PREEXEC, val);
- } else if (optionok(tmp, "root_postexec:", val)) {
+ if (val = iniparser_getstring(conf, vol, "root_postexec", NULL))
setoption(options, save, VOLOPT_ROOTPOSTEXEC, val);
- } else if (optionok(tmp, "postexec:", val)) {
+ if (val = iniparser_getstring(conf, vol, "postexec", NULL))
setoption(options, save, VOLOPT_POSTEXEC, val);
- } else if (optionok(tmp, "allowed_hosts:", val)) {
+ if (val = iniparser_getstring(conf, vol, "allowed_hosts", NULL))
setoption(options, save, VOLOPT_ALLOWED_HOSTS, val);
- } else if (optionok(tmp, "denied_hosts:", val)) {
+ if (val = iniparser_getstring(conf, vol, "denied_hosts", NULL))
setoption(options, save, VOLOPT_DENIED_HOSTS, val);
- } else if (optionok(tmp, "ea:", val)) {
- if (strcasecmp(val + 1, "ad") == 0)
+ if (val = iniparser_getstring(conf, vol, "umask", NULL))
+ options[VOLOPT_UMASK].i_value = (int)strtol(val, NULL, 8);
+
+ if (val = iniparser_getstring(conf, vol, "dperm", NULL))
+ options[VOLOPT_DPERM].i_value = (int)strtol(val, NULL, 8);
+
+ if (val = iniparser_getstring(conf, vol, "fperm", NULL))
+ options[VOLOPT_FPERM].i_value = (int)strtol(val, NULL, 8);
+
+ if (val = iniparser_getstring(conf, vol, "perm", NULL))
+ options[VOLOPT_DFLTPERM].i_value = (int)strtol(val, NULL, 8);
+
+ if (val = iniparser_getstring(conf, vol, "volsizelimit", NULL))
+ options[VOLOPT_LIMITSIZE].i_value = (uint32_t)strtoul(val, NULL, 10);
+
+ if (val = iniparser_getstring(conf, vol, "casefold", NULL)) {
+ if (strcasecmp(val, "tolower") == 0)
+ options[VOLOPT_CASEFOLD].i_value = AFPVOL_UMLOWER;
+ else if (strcasecmp(val, "toupper") == 0)
+ options[VOLOPT_CASEFOLD].i_value = AFPVOL_UMUPPER;
+ else if (strcasecmp(val, "xlatelower") == 0)
+ options[VOLOPT_CASEFOLD].i_value = AFPVOL_UUPPERMLOWER;
+ else if (strcasecmp(val, "xlateupper") == 0)
+ options[VOLOPT_CASEFOLD].i_value = AFPVOL_ULOWERMUPPER;
+ }
+
+ if (val = iniparser_getstring(conf, vol, "adouble", NULL)) {
+ if (strcasecmp(val, "v2") == 0)
+ options[VOLOPT_ADOUBLE].i_value = AD_VERSION2;
+ else if (strcasecmp(val, "ea") == 0)
+ options[VOLOPT_ADOUBLE].i_value = AD_VERSION_EA;
+ }
+
+ if (val = iniparser_getstring(conf, vol, "ea", NULL)) {
+ if (strcasecmp(val, "ad") == 0)
options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AD;
- else if (strcasecmp(val + 1, "sys") == 0)
+ else if (strcasecmp(val, "sys") == 0)
options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_SYS;
- else if (strcasecmp(val + 1, "none") == 0)
+ else if (strcasecmp(val, "none") == 0)
options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_NONE;
+ }
- } else if (optionok(tmp, "volsizelimit:", val)) {
- options[VOLOPT_LIMITSIZE].i_value = (uint32_t)strtoul(val + 1, NULL, 10);
-
- } else {
- /* ignore unknown options */
- LOG(log_debug, logtype_afpd, "ignoring unknown volume option: %s", tmp);
+ if (p = iniparser_getstrdup(conf, vol, "cnidserver", NULL)) {
+ if (q = strrchr(val, ':')) {
+ *q = 0;
+ setoption(options, save, VOLOPT_CNIDPORT, q + 1);
+ }
+ setoption(options, save, VOLOPT_CNIDSERVER, p);
+ LOG(log_debug, logtype_afpd, "CNID Server for volume '%s': %s:%s",
+ vol, p, q ? q + 1 : "4700");
+ free(p);
+ }
+ if (q = iniparser_getstrdup(conf, vol, "options", NULL)) {
+ if (p = strtok(q, ",")) {
+ while (p) {
+ if (strcasecmp(p, "ro") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_RO;
+ else if (strcasecmp(p, "nohex") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_NOHEX;
+ else if (strcasecmp(p, "usedots") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_USEDOTS;
+ else if (strcasecmp(p, "invisibledots") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_USEDOTS | AFPVOL_INV_DOTS;
+ else if (strcasecmp(p, "nostat") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_NOSTAT;
+ else if (strcasecmp(p, "preexec_close") == 0)
+ options[VOLOPT_PREEXEC].i_value = 1;
+ else if (strcasecmp(p, "root_preexec_close") == 0)
+ options[VOLOPT_ROOTPREEXEC].i_value = 1;
+ else if (strcasecmp(p, "upriv") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_UNIX_PRIV;
+ else if (strcasecmp(p, "nodev") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_NODEV;
+ else if (strcasecmp(p, "caseinsensitive") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_CASEINSEN;
+ else if (strcasecmp(p, "illegalseq") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_EILSEQ;
+ else if (strcasecmp(p, "tm") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_TM;
+ else if (strcasecmp(p, "searchdb") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_SEARCHDB;
+ else if (strcasecmp(p, "nonetids") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_NONETIDS;
+ else if (strcasecmp(p, "noacls") == 0)
+ options[VOLOPT_FLAGS].i_value &= ~AFPVOL_ACLS;
+ else if (strcasecmp(p, "nov2toeaconv") == 0)
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_NOV2TOEACONV;
+ p = strtok(NULL, ",");
+ }
+ }
+ free(q);
}
}
/* ------------------------------- */
static int creatvol(AFPObj *obj, struct passwd *pwd,
char *path, char *name,
- struct vol_option *options,
- const int user /* user defined volume */
- )
+ struct vol_option *options)
{
struct vol *volume;
int suffixlen, vlen, tmpvlen, u8mvlen, macvlen;
char tmpname[AFPVOL_U8MNAMELEN+1];
ucs2_t u8mtmpname[(AFPVOL_U8MNAMELEN+1)*2], mactmpname[(AFPVOL_MACNAMELEN+1)*2];
char suffix[6]; /* max is #FFFF */
- u_int16_t flags;
+ uint16_t flags;
LOG(log_debug, logtype_afpd, "createvol: Volume '%s'", name);
volume->v_ad_options = 0;
if ((volume->v_flags & AFPVOL_NODEV))
volume->v_ad_options |= ADVOL_NODEV;
- if ((volume->v_flags & AFPVOL_CACHE))
- volume->v_ad_options |= ADVOL_CACHE;
if ((volume->v_flags & AFPVOL_UNIX_PRIV))
volume->v_ad_options |= ADVOL_UNIXPRIV;
if ((volume->v_flags & AFPVOL_INV_DOTS))
volume->v_ad_options |= ADVOL_INVDOTS;
- if ((volume->v_flags & AFPVOL_NOADOUBLE))
- volume->v_ad_options |= ADVOL_NOADOUBLE;
if (options[VOLOPT_PASSWORD].c_value)
volume->v_password = strdup(options[VOLOPT_PASSWORD].c_value);
if ((volume->v_flags & AFPVOL_EILSEQ))
volume->v_utom_flags |= CONV__EILSEQ;
-#ifdef FORCE_UIDGID
- if (options[VOLOPT_FORCEUID].c_value) {
- volume->v_forceuid = strdup(options[VOLOPT_FORCEUID].c_value);
- } else {
- volume->v_forceuid = NULL; /* set as null so as to return 0 later on */
- }
-
- if (options[VOLOPT_FORCEGID].c_value) {
- volume->v_forcegid = strdup(options[VOLOPT_FORCEGID].c_value);
- } else {
- volume->v_forcegid = NULL; /* set as null so as to return 0 later on */
- }
-#endif
- if (!user) {
- if (options[VOLOPT_PREEXEC].c_value)
- volume->v_preexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_PREEXEC].c_value, pwd, path, name);
- volume->v_preexec_close = options[VOLOPT_PREEXEC].i_value;
+ if (options[VOLOPT_PREEXEC].c_value)
+ volume->v_preexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_PREEXEC].c_value, pwd, path, name);
+ volume->v_preexec_close = options[VOLOPT_PREEXEC].i_value;
- if (options[VOLOPT_POSTEXEC].c_value)
- volume->v_postexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_POSTEXEC].c_value, pwd, path, name);
+ if (options[VOLOPT_POSTEXEC].c_value)
+ volume->v_postexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_POSTEXEC].c_value, pwd, path, name);
- if (options[VOLOPT_ROOTPREEXEC].c_value)
- volume->v_root_preexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_ROOTPREEXEC].c_value, pwd, path, name);
- volume->v_root_preexec_close = options[VOLOPT_ROOTPREEXEC].i_value;
+ if (options[VOLOPT_ROOTPREEXEC].c_value)
+ volume->v_root_preexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_ROOTPREEXEC].c_value, pwd, path, name);
+ volume->v_root_preexec_close = options[VOLOPT_ROOTPREEXEC].i_value;
- if (options[VOLOPT_ROOTPOSTEXEC].c_value)
- volume->v_root_postexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_ROOTPOSTEXEC].c_value, pwd, path, name);
- }
+ if (options[VOLOPT_ROOTPOSTEXEC].c_value)
+ volume->v_root_postexec = volxlate(obj, NULL, MAXPATHLEN, options[VOLOPT_ROOTPOSTEXEC].c_value, pwd, path, name);
}
volume->v_dperm |= volume->v_perm;
volume->v_fperm |= volume->v_perm;
{
int mask_int;
char buf[MAXPATHLEN + 1], *p, *b;
- DSI *dsi = obj->handle;
+ DSI *dsi = obj->dsi;
struct sockaddr_storage client;
if (!args)
if ((p = strtok_r(buf, ",", &b)) == NULL) /* nothing, return okay */
return -1;
- if (obj->proto != AFPPROTO_DSI)
- return -1;
-
while (p) {
int ret;
char *ipaddr, *mask_char;
return 0;
}
-static void setextmap(char *ext, char *type, char *creator, int user)
-{
- struct extmap *em;
- int cnt;
-
- if (Extmap == NULL) {
- if (( Extmap = calloc(1, sizeof( struct extmap ))) == NULL ) {
- LOG(log_error, logtype_afpd, "setextmap: calloc: %s", strerror(errno) );
- return;
- }
- }
- ext++;
- for ( em = Extmap, cnt = 0; em->em_ext; em++, cnt++) {
- if ( (strdiacasecmp( em->em_ext, ext )) == 0 ) {
- break;
- }
- }
-
- if ( em->em_ext == NULL ) {
- if (!(Extmap = realloc( Extmap, sizeof( struct extmap ) * (cnt +2))) ) {
- LOG(log_error, logtype_afpd, "setextmap: realloc: %s", strerror(errno) );
- return;
- }
- (Extmap +cnt +1)->em_ext = NULL;
- em = Extmap +cnt;
- } else if ( !user ) {
- return;
- }
- if (em->em_ext)
- free(em->em_ext);
-
- if (!(em->em_ext = strdup( ext))) {
- LOG(log_error, logtype_afpd, "setextmap: strdup: %s", strerror(errno) );
- return;
- }
-
- if ( *type == '\0' ) {
- memcpy(em->em_type, "\0\0\0\0", sizeof( em->em_type ));
- } else {
- memcpy(em->em_type, type, sizeof( em->em_type ));
- }
- if ( *creator == '\0' ) {
- memcpy(em->em_creator, "\0\0\0\0", sizeof( em->em_creator ));
- } else {
- memcpy(em->em_creator, creator, sizeof( em->em_creator ));
- }
-}
-
-/* -------------------------- */
-static int extmap_cmp(const void *map1, const void *map2)
-{
- const struct extmap *em1 = map1;
- const struct extmap *em2 = map2;
- return strdiacasecmp(em1->em_ext, em2->em_ext);
-}
-
-static void sortextmap( void)
-{
- struct extmap *em;
-
- Extmap_cnt = 0;
- if ((em = Extmap) == NULL) {
- return;
- }
- while (em->em_ext) {
- em++;
- Extmap_cnt++;
- }
- if (Extmap_cnt) {
- qsort(Extmap, Extmap_cnt, sizeof(struct extmap), extmap_cmp);
- if (*Extmap->em_ext == 0) {
- /* the first line is really "." the default entry,
- * we remove the leading '.' in setextmap
- */
- Defextmap = Extmap;
- }
- }
-}
-
-/* ----------------------
- */
-static void free_extmap( void)
-{
- struct extmap *em;
-
- if (Extmap) {
- for ( em = Extmap; em->em_ext; em++) {
- free (em->em_ext);
- }
- free(Extmap);
- Extmap = NULL;
- Defextmap = Extmap;
- Extmap_cnt = 0;
- }
-}
-
/* ----------------------
*/
-static int volfile_changed(struct afp_volume_name *p)
+static int volfile_changed(struct afp_options *p)
{
struct stat st;
- char *name;
- if (p->full_name)
- name = p->full_name;
- else
- name = p->name;
-
- if (!stat( name, &st) && st.st_mtime > p->mtime) {
- p->mtime = st.st_mtime;
+ if (!stat(p->configfile, &st) && st.st_mtime > p->volfile.mtime) {
+ p->volfile.mtime = st.st_mtime;
return 1;
}
return 0;
}
+static int vol_section(const char *sec)
+{
+ if (STRCMP(sec, ==, INISEC_GLOBAL))
+ return 0;
+ if (STRCMP(sec, ==, INISEC_AFP))
+ return 0;
+ if (STRCMP(sec, ==, INISEC_CNID))
+ return 0;
+ return 1;
+}
+
/* ----------------------
- * Read a volume configuration file and add the volumes contained within to
+ * Read volumes from iniconfig and add the volumes contained within to
* the global volume list. This gets called from the forked afpd childs.
* The master now reads this too for Zeroconf announcements.
- *
- * If p2 is non-NULL, the file that is opened is
- * p1/p2
- *
- * Lines that begin with # and blank lines are ignored.
- * Volume lines are of the form:
- * <unix path> [<volume name>] [allow:<user>,<@group>,...] \
- * [codepage:<file>] [casefold:<num>]
- * <extension> TYPE [CREATOR]
- *
*/
-static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, char *p2, int user, struct passwd *pwent)
+static int readvolfile(AFPObj *obj, struct afp_volume_name *p1, struct passwd *pwent)
{
- FILE *fp;
char path[MAXPATHLEN + 1];
- char tmp[MAXPATHLEN + 1];
char volname[AFPVOL_U8MNAMELEN + 1];
- char buf[BUFSIZ];
- char type[5], creator[5];
- char *u, *p;
+ char tmp[MAXPATHLEN + 1];
+ char *u;
+ const char *p;
int fd;
int i;
- struct passwd *pw;
- struct vol_option save_options[VOLOPT_NUM];
- struct vol_option default_options[VOLOPT_NUM];
- struct vol_option options[VOLOPT_NUM];
- struct stat st;
+ struct passwd *pw;
+ struct vol_option save_options[VOLOPT_NUM];
+ struct vol_option default_options[VOLOPT_NUM];
+ struct vol_option options[VOLOPT_NUM];
- if (!p1->name)
- return -1;
- p1->mtime = 0;
- strcpy( path, p1->name );
- if ( p2 != NULL ) {
- strcat( path, "/" );
- strcat( path, p2 );
- if (p1->full_name) {
- free(p1->full_name);
- }
- p1->full_name = strdup(path);
- }
-
- if (NULL == ( fp = fopen( path, "r" )) ) {
- return( -1 );
- }
- fd = fileno(fp);
- if (fd != -1 && !fstat( fd, &st) ) {
- p1->mtime = st.st_mtime;
- }
+ LOG(log_debug, logtype_afpd, "readvolfile: BEGIN");
- /* try putting a read lock on the volume file twice, sleep 1 second if first attempt fails */
- int retries = 2;
- while (1) {
- if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) {
- retries--;
- if (!retries) {
- LOG(log_error, logtype_afpd, "readvolfile: can't lock volume file \"%s\"", path);
- if ( fclose( fp ) != 0 ) {
- LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) );
- }
- return -1;
- }
- sleep(1);
- continue;
- }
- break;
- }
+ p1->mtime = 0;
memset(default_options, 0, sizeof(default_options));
/* Enable some default options for all volumes */
- default_options[VOLOPT_FLAGS].i_value |= AFPVOL_CACHE;
#ifdef HAVE_ACLS
default_options[VOLOPT_FLAGS].i_value |= AFPVOL_ACLS;
#endif
default_options[VOLOPT_EA_VFS].i_value = AFPVOL_EA_AUTO;
- LOG(log_maxdebug, logtype_afpd, "readvolfile: seeding default umask: %04o",
- obj->options.umask);
default_options[VOLOPT_UMASK].i_value = obj->options.umask;
memcpy(save_options, default_options, sizeof(options));
- LOG(log_debug, logtype_afpd, "readvolfile: \"%s\"", path);
+ int secnum = iniparser_getnsec(obj->iniconfig);
+ LOG(log_debug, logtype_afpd, "readvolfile: sections: %d", secnum);
+ const char *secname;
- while ( myfgets( buf, sizeof( buf ), fp ) != NULL ) {
- initline( strlen( buf ), buf );
- parseline( sizeof( path ) - 1, path );
- switch ( *path ) {
- case '\0' :
- case '#' :
+ for (i = 0; i < secnum; i++) {
+ secname = iniparser_getsecname(obj->iniconfig, i);
+ if (!vol_section(secname))
continue;
- case ':':
- /* change the default options for this file */
- if (strncmp(path, VOLOPT_DEFAULT, VOLOPT_DEFAULT_LEN) == 0) {
- volfree(default_options, save_options);
- memcpy(default_options, save_options, sizeof(options));
- *tmp = '\0';
- for (i = 0; i < VOLOPT_NUM; i++) {
- if (parseline( sizeof( path ) - VOLOPT_DEFAULT_LEN - 1,
- path + VOLOPT_DEFAULT_LEN) < 0)
- break;
- volset(default_options, NULL, tmp, sizeof(tmp) - 1,
- path + VOLOPT_DEFAULT_LEN);
- }
- }
- break;
+ strlcpy(volname, secname, AFPVOL_U8MNAMELEN);
+ LOG(log_debug, logtype_afpd, "readvolfile: volume: %s", volname);
- case '~' :
- if (( p = strchr( path, '/' )) != NULL ) {
- *p++ = '\0';
- }
- u = path;
- u++;
- if ( *u == '\0' ) {
- u = obj->username;
- }
- if ( u == NULL || *u == '\0' || ( pw = getpwnam( u )) == NULL ) {
- continue;
- }
- strcpy( tmp, pw->pw_dir );
- if ( p != NULL && *p != '\0' ) {
- strcat( tmp, "/" );
- strcat( tmp, p );
- }
- /* fall through */
-
- case '/' :
- /* send path through variable substitution */
- if (*path != '~') /* need to copy path to tmp */
- strcpy(tmp, path);
- if (!pwent && obj->username)
- pwent = getpwnam(obj->username);
-
- if (volxlate(obj, path, sizeof(path) - 1, tmp, pwent, NULL, NULL) == NULL)
- continue;
-
- /* this is sort of braindead. basically, i want to be
- * able to specify things in any order, but i don't want to
- * re-write everything. */
+ if ((p = iniparser_getstrdup(obj->iniconfig, secname, "path", NULL)) == NULL)
+ continue;
+ strlcpy(path, p, MAXPATHLEN);
+ strcpy(tmp, path);
- memcpy(options, default_options, sizeof(options));
- *volname = '\0';
- /* read in up to VOLOP_NUM possible options */
- for (i = 0; i < VOLOPT_NUM; i++) {
- if (parseline( sizeof( tmp ) - 1, tmp ) < 0)
- break;
+ if (!pwent && obj->username)
+ pwent = getpwnam(obj->username);
- volset(options, default_options, volname, sizeof(volname) - 1, tmp);
- }
-
- /* check allow/deny lists (if not afpd master loading volumes for Zeroconf reg.):
- allow -> either no list (-1), or in list (1)
- deny -> either no list (-1), or not in list (0) */
- if (parent_or_child == 0
- ||
- (accessvol(options[VOLOPT_ALLOW].c_value, obj->username) &&
- (accessvol(options[VOLOPT_DENY].c_value, obj->username) < 1) &&
- hostaccessvol(VOLOPT_ALLOWED_HOSTS, volname, options[VOLOPT_ALLOWED_HOSTS].c_value, obj) &&
- (hostaccessvol(VOLOPT_DENIED_HOSTS, volname, options[VOLOPT_DENIED_HOSTS].c_value, obj) < 1))) {
-
- /* handle read-only behaviour. semantics:
- * 1) neither the rolist nor the rwlist exist -> rw
- * 2) rolist exists -> ro if user is in it.
- * 3) rwlist exists -> ro unless user is in it. */
- if (parent_or_child == 1
- &&
- ((options[VOLOPT_FLAGS].i_value & AFPVOL_RO) == 0)
- &&
- ((accessvol(options[VOLOPT_ROLIST].c_value, obj->username) == 1) ||
- !accessvol(options[VOLOPT_RWLIST].c_value, obj->username)))
- options[VOLOPT_FLAGS].i_value |= AFPVOL_RO;
+ if (volxlate(obj, path, sizeof(path) - 1, tmp, pwent, NULL, NULL) == NULL)
+ continue;
- /* do variable substitution for volname */
- if (volxlate(obj, tmp, sizeof(tmp) - 1, volname, pwent, path, NULL) == NULL)
- continue;
+ memcpy(options, default_options, sizeof(options));
+ volset(obj->iniconfig, secname, options, default_options);
+
+ /* check allow/deny lists (if not afpd master loading volumes for Zeroconf reg.):
+ allow -> either no list (-1), or in list (1)
+ deny -> either no list (-1), or not in list (0) */
+ if (parent_or_child == 0
+ ||
+ (accessvol(options[VOLOPT_ALLOW].c_value, obj->username) &&
+ (accessvol(options[VOLOPT_DENY].c_value, obj->username) < 1) &&
+ hostaccessvol(VOLOPT_ALLOWED_HOSTS, volname, options[VOLOPT_ALLOWED_HOSTS].c_value, obj) &&
+ (hostaccessvol(VOLOPT_DENIED_HOSTS, volname, options[VOLOPT_DENIED_HOSTS].c_value, obj) < 1))) {
+
+ /* handle read-only behaviour. semantics:
+ * 1) neither the rolist nor the rwlist exist -> rw
+ * 2) rolist exists -> ro if user is in it.
+ * 3) rwlist exists -> ro unless user is in it. */
+ if (parent_or_child == 1
+ &&
+ ((options[VOLOPT_FLAGS].i_value & AFPVOL_RO) == 0)
+ &&
+ ((accessvol(options[VOLOPT_ROLIST].c_value, obj->username) == 1) ||
+ !accessvol(options[VOLOPT_RWLIST].c_value, obj->username)))
+ options[VOLOPT_FLAGS].i_value |= AFPVOL_RO;
- creatvol(obj, pwent, path, tmp, options, p2 != NULL);
+ /* do variable substitution for volname */
+ if (volxlate(obj, tmp, sizeof(tmp) - 1, volname, pwent, path, NULL) == NULL) {
+ volfree(options, default_options);
+ continue;
}
- volfree(options, default_options);
- break;
-
- case '.' :
- parseline( sizeof( type ) - 1, type );
- parseline( sizeof( creator ) - 1, creator );
- setextmap( path, type, creator, user);
- break;
- default :
- break;
+ creatvol(obj, pwent, path, tmp, options);
}
+ volfree(options, default_options);
}
volfree(save_options, NULL);
- sortextmap();
- if ( fclose( fp ) != 0 ) {
- LOG(log_error, logtype_afpd, "readvolfile: fclose: %s", strerror(errno) );
- }
p1->loaded = 1;
return( 0 );
}
free(vol->v_cnidscheme);
free(vol->v_dbpath);
free(vol->v_gvs);
-#ifdef FORCE_UIDGID
- free(vol->v_forceuid);
- free(vol->v_forcegid);
-#endif /* FORCE_UIDGID */
if (vol->v_uuid)
free(vol->v_uuid);
}
char buf[512];
long long int bandsize = -1;
- EC_NULL_LOGSTR(file = fopen(path, "r"),
- "get_tm_bandsize(\"%s\"): %s",
- path, strerror(errno));
+ EC_NULL_LOGSTR( file = fopen(path, "r"),
+ "get_tm_bandsize(\"%s\"): %s",
+ path, strerror(errno) );
while (fgets(buf, sizeof(buf), file) != NULL) {
if (strstr(buf, "band-size") == NULL)
DIR *dir = NULL;
const struct dirent *entry;
- EC_NULL(dir = opendir(path));
+ EC_NULL( dir = opendir(path) );
while ((entry = readdir(dir)) != NULL)
count++;
* 4) readdir "\1.sparsebundle/bands/" counting files
* 5) calculate used size as: (file_count - 1) * band-size
*
- * The result is cached in volume->v_tm_cachetime for TM_USED_CACHETIME secounds.
- * The cached value volume->v_tm_cachetime is updated by volume->v_appended. The latter
- * is increased by X every time the client appends X bytes to a file (in fork.c).
+ * The result of the calculation is returned in "volume->v_tm_used".
+ * "volume->v_appended" gets reset to 0.
+ * "volume->v_tm_cachetime" is updated with the current time from time(NULL).
+ *
+ * "volume->v_tm_used" is cached for TM_USED_CACHETIME seconds and updated by
+ * "volume->v_appended". The latter is increased by X every time the client
+ * appends X bytes to a file (in fork.c).
*
* @param vol (rw) volume to calculate
- * @return Estimated used size in bytes, -1 on error
+ * @return 0 on success, -1 on error
*/
#define TM_USED_CACHETIME 60 /* cache for 60 seconds */
-static VolSpace get_tm_used(struct vol *vol)
+static int get_tm_used(struct vol * restrict vol)
{
EC_INIT;
long long int bandsize;
if (vol->v_tm_cachetime
&& ((vol->v_tm_cachetime + TM_USED_CACHETIME) >= now)) {
if (vol->v_tm_used == -1)
- return -1;
+ EC_FAIL;
vol->v_tm_used += vol->v_appended;
vol->v_appended = 0;
- LOG(log_debug, logtype_afpd, "getused(%s): used(cached): %jd", vol->v_path, (intmax_t)vol->v_tm_used);
- return vol->v_tm_used;
+ LOG(log_debug, logtype_afpd, "getused(\"%s\"): cached: %" PRIu64 " bytes",
+ vol->v_path, vol->v_tm_used);
+ return 0;
}
vol->v_tm_cachetime = now;
- EC_NULL(dir = opendir(vol->v_path));
+ EC_NULL( dir = opendir(vol->v_path) );
while ((entry = readdir(dir)) != NULL) {
if (((p = strstr(entry->d_name, "sparsebundle")) != NULL)
&& (strlen(entry->d_name) == (p + strlen("sparsebundle") - entry->d_name))) {
- EC_NULL_LOG(infoplist = bformat("%s/%s/%s", vol->v_path, entry->d_name, "Info.plist"));
+ EC_NULL_LOG( infoplist = bformat("%s/%s/%s", vol->v_path, entry->d_name, "Info.plist") );
if ((bandsize = get_tm_bandsize(cfrombstr(infoplist))) == -1)
continue;
- EC_NULL_LOG(bandsdir = bformat("%s/%s/%s/", vol->v_path, entry->d_name, "bands"));
+ EC_NULL_LOG( bandsdir = bformat("%s/%s/%s/", vol->v_path, entry->d_name, "bands") );
if ((links = get_tm_bands(cfrombstr(bandsdir))) == -1)
continue;
used += (links - 1) * bandsize;
- LOG(log_debug, logtype_afpd, "getused: %s, used: %jd", cfrombstr(bandsdir), (intmax_t)used);
+ LOG(log_debug, logtype_afpd, "getused(\"%s\"): bands: %" PRIu64 " bytes",
+ cfrombstr(bandsdir), used);
}
}
-EC_CLEANUP:
- if (ret != 0)
- used = -1;
vol->v_tm_used = used;
+
+EC_CLEANUP:
if (infoplist)
bdestroy(infoplist);
if (bandsdir)
bdestroy(bandsdir);
if (dir)
closedir(dir);
- LOG(log_debug, logtype_afpd, "getused(%s), used: %jd", vol->v_path, (intmax_t)used);
- return used;
+
+ LOG(log_debug, logtype_afpd, "getused(\"%s\"): %" PRIu64 " bytes", vol->v_path, vol->v_tm_used);
+
+ EC_EXIT;
}
static int getvolspace(struct vol *vol,
- u_int32_t *bfree, u_int32_t *btotal,
- VolSpace *xbfree, VolSpace *xbtotal, u_int32_t *bsize)
+ uint32_t *bfree, uint32_t *btotal,
+ VolSpace *xbfree, VolSpace *xbtotal, uint32_t *bsize)
{
int spaceflag, rc;
- u_int32_t maxsize;
+ uint32_t maxsize;
VolSpace used;
#ifndef NO_QUOTA_SUPPORT
VolSpace qfree, qtotal;
spaceflag = AFPVOL_GVSMASK & vol->v_flags;
/* report up to 2GB if afp version is < 2.2 (4GB if not) */
- maxsize = (vol->v_flags & AFPVOL_A2VOL) ? 0x01fffe00 :
- (((afp_version < 22) || (vol->v_flags & AFPVOL_LIMITSIZE))
- ? 0x7fffffffL : 0xffffffffL);
+ maxsize = (afp_version < 22) ? 0x7fffffffL : 0xffffffffL;
#ifdef AFS
if ( spaceflag == AFPVOL_NONE || spaceflag == AFPVOL_AFSGVS ) {
return( rc );
}
-#define min(a,b) ((a)<(b)?(a):(b))
#ifndef NO_QUOTA_SUPPORT
if ( spaceflag == AFPVOL_NONE || spaceflag == AFPVOL_UQUOTA ) {
if ( uquota_getvolspace( vol, &qfree, &qtotal, *bsize ) == AFP_OK ) {
vol->v_flags = ( ~AFPVOL_GVSMASK & vol->v_flags ) | AFPVOL_UQUOTA;
- *xbfree = min(*xbfree, qfree);
- *xbtotal = min( *xbtotal, qtotal);
+ *xbfree = MIN(*xbfree, qfree);
+ *xbtotal = MIN(*xbtotal, qtotal);
goto getvolspace_done;
}
}
getvolspace_done:
if (vol->v_limitsize) {
- if ((used = get_tm_used(vol)) == -1)
+ if (get_tm_used(vol) != 0)
return AFPERR_MISC;
- *xbtotal = min(*xbtotal, (vol->v_limitsize * 1024 * 1024));
- *xbfree = min(*xbfree, *xbtotal < used ? 0 : *xbtotal - used);
+ *xbtotal = MIN(*xbtotal, (vol->v_limitsize * 1024 * 1024));
+ *xbfree = MIN(*xbfree, *xbtotal < vol->v_tm_used ? 0 : *xbtotal - vol->v_tm_used);
- LOG(log_debug, logtype_afpd, "volparams: total: %jd, used: %jd, free: %jd",
- (intmax_t)(*xbtotal), (intmax_t)used, (intmax_t)(*xbfree));
+ LOG(log_debug, logtype_afpd,
+ "volparams: total: %" PRIu64 ", used: %" PRIu64 ", free: %" PRIu64 " bytes",
+ *xbtotal, vol->v_tm_used, *xbfree);
}
- *bfree = min( *xbfree, maxsize);
- *btotal = min( *xbtotal, maxsize);
+ *bfree = MIN(*xbfree, maxsize);
+ *btotal = MIN(*xbtotal, maxsize);
return( AFP_OK );
}
* set volume creation date
* avoid duplicate, well at least it tries
*/
-static void vol_setdate(u_int16_t id, struct adouble *adp, time_t date)
+static void vol_setdate(uint16_t id, struct adouble *adp, time_t date)
{
struct vol *volume;
struct vol *vol = Volumes;
}
/* ----------------------- */
-static int getvolparams( u_int16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen)
+static int getvolparams( uint16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen)
{
struct adouble ad;
int bit = 0, isad = 1;
- u_int32_t aint;
+ uint32_t aint;
u_short ashort;
- u_int32_t bfree, btotal, bsize;
+ uint32_t bfree, btotal, bsize;
VolSpace xbfree, xbtotal; /* extended bytes */
char *data, *nameoff = NULL;
char *slash;
* For MacOS8.x support we need to create the
* .Parent file here if it doesn't exist. */
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- if ( ad_open_metadata( vol->v_path, ADFLAGS_DIR, O_CREAT, &ad) < 0 ) {
+ /* Convert adouble:v2 to adouble:ea on the fly */
+ (void)ad_convert(vol->v_path, st, vol);
+
+ ad_init(&ad, vol);
+ if (ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR | ADFLAGS_CREATE, 0666) != 0 ) {
isad = 0;
vol->v_ctime = AD_DATE_FROM_UNIX(st->st_mtime);
}
/* prior 2.1 only VOLPBIT_ATTR_RO is defined */
if (afp_version > 20) {
- if (0 == (vol->v_flags & AFPVOL_NOFILEID) && vol->v_cdb != NULL &&
- (vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) {
+ if (vol->v_cdb != NULL && (vol->v_cdb->flags & CNID_FLAG_PERSISTENT))
ashort |= VOLPBIT_ATTR_FILEID;
- }
ashort |= VOLPBIT_ATTR_CATSEARCH;
if (afp_version >= 30) {
#ifndef NO_LARGE_VOL_SUPPORT
case VOLPBIT_XBFREE :
xbfree = hton64( xbfree );
-#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
- bcopy(&xbfree, data, sizeof(xbfree));
-#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
memcpy(data, &xbfree, sizeof( xbfree ));
-#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
data += sizeof( xbfree );
break;
case VOLPBIT_XBTOTAL :
xbtotal = hton64( xbtotal );
-#if defined(__GNUC__) && defined(HAVE_GCC_MEMCPY_BUG)
- bcopy(&xbtotal, data, sizeof(xbtotal));
-#else /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
memcpy(data, &xbtotal, sizeof( xbtotal ));
-#endif /* __GNUC__ && HAVE_GCC_MEMCPY_BUG */
data += sizeof( xbfree );
break;
#endif /* ! NO_LARGE_VOL_SUPPORT */
case VOLPBIT_NAME :
nameoff = data;
- data += sizeof( u_int16_t );
+ data += sizeof( uint16_t );
break;
case VOLPBIT_BSIZE: /* block size */
data += aint;
}
if ( isad ) {
- ad_close_metadata( &ad);
+ ad_close(&ad, ADFLAGS_HF);
}
*buflen = data - buf;
return( AFP_OK );
}
/* ------------------------- */
-static int stat_vol(u_int16_t bitmap, struct vol *vol, char *rbuf, size_t *rbuflen)
+static int stat_vol(uint16_t bitmap, struct vol *vol, char *rbuf, size_t *rbuflen)
{
struct stat st;
int ret;
/* ------------------------------- */
void load_volumes(AFPObj *obj)
{
+ EC_INIT;
+ int fd = -1;
struct passwd *pwent;
-
- if (Volumes) {
- int changed = 0;
-
- /* check files date */
- if (obj->options.defaultvol.loaded) {
- changed = volfile_changed(&obj->options.defaultvol);
- }
- if (obj->options.systemvol.loaded) {
- changed |= volfile_changed(&obj->options.systemvol);
- }
- if (obj->options.uservol.loaded) {
- changed |= volfile_changed(&obj->options.uservol);
- }
- if (!changed)
- return;
-
- free_extmap();
- free_volumes();
- }
+ struct stat st;
+ int retries = 0;
if (parent_or_child == 0) {
LOG(log_debug, logtype_afpd, "load_volumes: AFP MASTER");
LOG(log_debug, logtype_afpd, "load_volumes: user: %s", obj->username);
}
- pwent = getpwnam(obj->username);
- if ( (obj->options.flags & OPTION_USERVOLFIRST) == 0 ) {
- readvolfile(obj, &obj->options.systemvol, NULL, 0, pwent);
+ if (Volumes) {
+ if (!volfile_changed(&obj->options))
+ return;
+ free_volumes();
}
- if ((*obj->username == '\0') || (obj->options.flags & OPTION_NOUSERVOL)) {
- readvolfile(obj, &obj->options.defaultvol, NULL, 1, pwent);
- } else if (pwent) {
- /*
- * Read user's AppleVolumes or .AppleVolumes file
- * If neither are readable, read the default volumes file. if
- * that doesn't work, create a user share.
- */
- if (obj->options.uservol.name) {
- free(obj->options.uservol.name);
- }
- obj->options.uservol.name = strdup(pwent->pw_dir);
- if ( readvolfile(obj, &obj->options.uservol, "AppleVolumes", 1, pwent) < 0 &&
- readvolfile(obj, &obj->options.uservol, ".AppleVolumes", 1, pwent) < 0 &&
- readvolfile(obj, &obj->options.uservol, "applevolumes", 1, pwent) < 0 &&
- readvolfile(obj, &obj->options.uservol, ".applevolumes", 1, pwent) < 0 &&
- obj->options.defaultvol.name != NULL ) {
- if (readvolfile(obj, &obj->options.defaultvol, NULL, 1, pwent) < 0)
- creatvol(obj, pwent, pwent->pw_dir, NULL, NULL, 1);
+ /* try putting a read lock on the volume file twice, sleep 1 second if first attempt fails */
+
+ fd = open(obj->options.configfile, O_RDWR);
+
+ while (retries < 2) {
+ if ((read_lock(fd, 0, SEEK_SET, 0)) != 0) {
+ retries++;
+ if (!retries) {
+ LOG(log_error, logtype_afpd, "readvolfile: can't lock configfile \"%s\"",
+ obj->options.configfile);
+ EC_FAIL;
+ }
+ sleep(1);
+ continue;
}
- }
- if ( obj->options.flags & OPTION_USERVOLFIRST ) {
- readvolfile(obj, &obj->options.systemvol, NULL, 0, pwent );
+ break;
}
- if ( obj->options.closevol ) {
- struct vol *vol;
+ if (obj->iniconfig)
+ iniparser_freedict(obj->iniconfig);
+ LOG(log_debug, logtype_afpd, "load_volumes: reloading: %s", obj->options.configfile);
+ obj->iniconfig = iniparser_load(obj->options.configfile);
+ if (obj->username)
+ pwent = getpwnam(obj->username);
+ else
+ pwent = NULL;
+
+ readvolfile(obj, &obj->options.volfile, pwent);
+
+ if ( obj->options.flags & OPTION_CLOSEVOL) {
+ struct vol *vol;
for ( vol = Volumes; vol; vol = vol->v_next ) {
if (vol->v_deleted && !vol->v_new ) {
of_closevol(vol);
}
}
}
+
+EC_CLEANUP:
+ if (fd != -1)
+ (void)close(fd);
+ return;
}
/* ------------------------------- */
/* set password bit if there's a volume password */
*data = (volume->v_password) ? AFPSRVR_PASSWD : 0;
- /* Apple 2 clients running ProDOS-8 expect one volume to have
- bit 0 of this byte set. They will not recognize anything
- on the server unless this is the case. I have not
- completely worked this out, but it's related to booting
- from the server. Support for that function is a ways
- off.. <shirsch@ibm.net> */
- *data |= (volume->v_flags & AFPVOL_A2VOL) ? AFPSRVR_CONFIGINFO : 0;
*data++ |= 0; /* UNIX PRIVS BIT ..., OSX doesn't seem to use it, so we don't either */
*data++ = len;
memcpy(data, namebuf, len );
return AFPERR_PARAM;
}
tv.tv_sec = AD_DATE_FROM_UNIX(tv.tv_sec);
- memcpy(data, &tv.tv_sec, sizeof( u_int32_t));
- data += sizeof( u_int32_t);
+ memcpy(data, &tv.tv_sec, sizeof( uint32_t));
+ data += sizeof( uint32_t);
*data = vcnt;
return( AFP_OK );
}
}
/* ------------------------- */
-static int volume_openDB(struct vol *volume)
+static int volume_openDB(const AFPObj *obj, struct vol *volume)
{
int flags = 0;
}
LOG(log_info, logtype_afpd, "CNID server: %s:%s",
- volume->v_cnidserver ? volume->v_cnidserver : Cnid_srv,
- volume->v_cnidport ? volume->v_cnidport : Cnid_port);
-
-#if 0
-/* Found this in branch dir-rewrite, maybe we want to use it sometimes */
-
- /* Legacy pre 2.1 way of sharing eg CD-ROM */
- if (strcmp(volume->v_cnidscheme, "last") == 0) {
- /* "last" is gone. We support it by switching to in-memory "tdb" */
- volume->v_cnidscheme = strdup("tdb");
- flags |= CNID_FLAG_MEMORY;
- }
-
- /* New way of sharing CD-ROM */
- if (volume->v_flags & AFPVOL_CDROM) {
- flags |= CNID_FLAG_MEMORY;
- if (strcmp(volume->v_cnidscheme, "tdb") != 0) {
- free(volume->v_cnidscheme);
- volume->v_cnidscheme = strdup("tdb");
- LOG(log_info, logtype_afpd, "Volume %s is ejectable, switching to scheme %s.",
- volume->v_path, volume->v_cnidscheme);
- }
- }
-#endif
+ 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 : Cnid_srv,
- volume->v_cnidport ? volume->v_cnidport : Cnid_port);
+ volume->v_cnidserver ? volume->v_cnidserver : obj->options.Cnid_srv,
+ volume->v_cnidport ? volume->v_cnidport : obj->options.Cnid_port);
if ( ! volume->v_cdb && ! (flags & CNID_FLAG_MEMORY)) {
/* The first attempt failed and it wasn't yet an attempt to open in-memory */
"Check server messages for details!");
kill(getpid(), SIGUSR2);
/* deactivate cnid caching/storing in AppleDouble files */
- volume->v_flags &= ~AFPVOL_CACHE;
}
#endif
}
struct dir *dir;
int len, ret;
size_t namelen;
- u_int16_t bitmap;
+ uint16_t bitmap;
char path[ MAXPATHLEN + 1];
char *vol_uname;
char *vol_mname;
if (( volume->v_flags & AFPVOL_OPEN ) ) {
/* the volume is already open */
-#ifdef FORCE_UIDGID
- set_uidgid ( volume );
-#endif
return stat_vol(bitmap, volume, rbuf, rbuflen);
}
}
}
-#ifdef FORCE_UIDGID
- set_uidgid ( volume );
-#endif
-
if (volume->v_preexec) {
if ((ret = afprun(0, volume->v_preexec, NULL)) && volume->v_preexec_close) {
LOG(log_error, logtype_afpd, "afp_openvol(%s): preexec : %d", volume->v_path, ret );
volume->v_root = dir;
curdir = dir;
- if (volume_openDB(volume) < 0) {
+ if (volume_openDB(obj, volume) < 0) {
LOG(log_error, logtype_afpd, "Fatal error: cannot open CNID or invalid CNID backend for %s: %s",
volume->v_path, volume->v_cnidscheme);
ret = AFPERR_MISC;
if (ret == AFP_OK) {
handle_special_folders(volume);
savevolinfo(volume,
- volume->v_cnidserver ? volume->v_cnidserver : Cnid_srv,
- volume->v_cnidport ? volume->v_cnidport : Cnid_port);
+ volume->v_cnidserver ? volume->v_cnidserver : obj->options.Cnid_srv,
+ volume->v_cnidport ? volume->v_cnidport : obj->options.Cnid_port);
/*
int afp_closevol(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen)
{
struct vol *vol;
- u_int16_t vid;
+ uint16_t vid;
*rbuflen = 0;
ibuf += 2;
}
/* ------------------------- */
-struct vol *getvolbyvid(const u_int16_t vid )
+struct vol *getvolbyvid(const uint16_t vid )
{
struct vol *vol;
return( NULL );
}
-#ifdef FORCE_UIDGID
- set_uidgid ( vol );
-#endif /* FORCE_UIDGID */
-
current_vol = vol;
return( vol );
}
-/* ------------------------ */
-static int ext_cmp_key(const void *key, const void *obj)
-{
- const char *p = key;
- const struct extmap *em = obj;
- return strdiacasecmp(p, em->em_ext);
-}
-struct extmap *getextmap(const char *path)
-{
- char *p;
- struct extmap *em;
-
- if (!Extmap_cnt || NULL == ( p = strrchr( path, '.' )) ) {
- return( Defextmap );
- }
- p++;
- if (!*p) {
- return( Defextmap );
- }
- em = bsearch(p, Extmap, Extmap_cnt, sizeof(struct extmap), ext_cmp_key);
- if (em) {
- return( em );
- } else {
- return( Defextmap );
- }
-}
-
-/* ------------------------- */
-struct extmap *getdefextmap(void)
-{
- return( Defextmap );
-}
-
/* --------------------------
poll if a volume is changed by other processes.
return
struct timeval tv;
struct stat st;
- if (!(afp_version > 21 && obj->options.server_notif))
+ if (!(afp_version > 21 && obj->options.flags & OPTION_SERVERNOTIF))
return 0;
if ( gettimeofday( &tv, NULL ) < 0 )
if ( (vol->v_flags & AFPVOL_OPEN) && vol->v_mtime + 30 < tv.tv_sec) {
if ( !stat( vol->v_path, &st ) && vol->v_mtime != st.st_mtime ) {
vol->v_mtime = st.st_mtime;
- if (!obj->attention(obj->handle, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED))
+ if (!obj->attention(obj->dsi, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED))
return -1;
return 1;
}
/* 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.server_notif) {
- obj->attention(obj->handle, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED);
+ if (afp_version < 32 && obj->options.flags & OPTION_SERVERNOTIF) {
+ obj->attention(obj->dsi, AFPATTN_NOTIFY | AFPATTN_VOLCHANGED);
}
}
}
int afp_getvolparams(AFPObj *obj _U_, char *ibuf, size_t ibuflen _U_,char *rbuf, size_t *rbuflen)
{
struct vol *vol;
- u_int16_t vid, bitmap;
+ uint16_t vid, bitmap;
ibuf += 2;
memcpy(&vid, ibuf, sizeof( vid ));
{
struct adouble ad;
struct vol *vol;
- u_int16_t vid, bitmap;
- u_int32_t aint;
+ uint16_t vid, bitmap;
+ uint32_t aint;
ibuf += 2;
*rbuflen = 0;
if (bitmap != (1 << VOLPBIT_BDATE))
return AFPERR_BITMAP;
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- if ( ad_open( vol->v_path, ADFLAGS_HF|ADFLAGS_DIR, O_RDWR,
- 0666, &ad) < 0 ) {
+ ad_init(&ad, vol);
+ if ( ad_open(&ad, vol->v_path, ADFLAGS_HF | ADFLAGS_DIR | ADFLAGS_RDWR) < 0 ) {
if (errno == EROFS)
return AFPERR_VLOCK;
return( AFP_OK );
}
-/* ------------------------- */
-int wincheck(const struct vol *vol, const char *path)
-{
- int len;
-
- if (!(vol->v_flags & AFPVOL_MSWINDOWS))
- return 1;
-
- /* empty paths are not allowed */
- if ((len = strlen(path)) == 0)
- return 0;
-
- /* leading or trailing whitespaces are not allowed, carriage returns
- * and probably other whitespace is okay, tabs are not allowed
- */
- if ((path[0] == ' ') || (path[len-1] == ' '))
- return 0;
-
- /* certain characters are not allowed */
- if (strpbrk(path, MSWINDOWS_BADCHARS))
- return 0;
-
- /* everything else is okay */
- return 1;
-}
-
-
/*
* precreate a folder
* this is only intended for folders in the volume root
{
char *p,*q,*r;
struct adouble ad;
- u_int16_t attr;
+ uint16_t attr;
struct stat st;
int ret;
if ( !ret && folder->hide) {
/* Hide it */
- ad_init(&ad, vol->v_adouble, vol->v_ad_options);
- if (ad_open_metadata( p, ADFLAGS_DIR, O_CREAT, &ad) < 0) {
- free (p);
+ 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);
}
memcpy(ad_entry(&ad, ADEID_FINDERI) + FINDERINFO_FRFLAGOFF,&attr, sizeof(attr));
}
- ad_flush( &ad );
- ad_close_metadata( &ad);
+ ad_flush(&ad);
+ ad_close(&ad, ADFLAGS_HF);
}
free(p);
free(q);
return Volumes;
}
-void unload_volumes_and_extmap(void)
+void unload_volumes(void)
{
LOG(log_debug, logtype_afpd, "unload_volumes_and_extmap");
- free_extmap();
free_volumes();
}