X-Git-Url: https://arthur.barton.de/gitweb/?p=netatalk.git;a=blobdiff_plain;f=libatalk%2Futil%2Fnetatalk_conf.c;h=16ade10c0b8953ddd26b4f5fe5c2af30119176d7;hp=2e1812ddcc0e3cc38aa3f09ec42dbe916421147b;hb=HEAD;hpb=2db3226555567f73a833a6d832aa77099c9de3ec diff --git a/libatalk/util/netatalk_conf.c b/libatalk/util/netatalk_conf.c index 2e1812dd..16ade10c 100644 --- a/libatalk/util/netatalk_conf.c +++ b/libatalk/util/netatalk_conf.c @@ -547,6 +547,36 @@ static int getoption_bool(const dictionary *conf, const char *vol, const char *o return result; } +/*! + * Get boolean option from volume, default section or global - use default value if not set + * + * Order of precedence: volume -> default section -> global -> default value + * + * "vdg" means volume, default section or global + * + * @param conf (r) config handle + * @param vol (r) volume name (must be section name ie wo vars expanded) + * @param opt (r) option + * @param defsec (r) if "option" is not found in "vol", try to find it in section "defsec" + * @param defval (r) if neither "vol" nor "defsec" contain "opt" return "defval" + * + * @returns const option string from "vol" or "defsec", or "defval" if not found + */ +static int vdgoption_bool(const dictionary *conf, const char *vol, const char *opt, const char *defsec, int defval) +{ + int result; + + result = atalk_iniparser_getboolean(conf, vol, opt, -1); + + if ((result == -1) && (defsec != NULL)) + result = atalk_iniparser_getboolean(conf, defsec, opt, -1); + + if (result == -1) + result = atalk_iniparser_getboolean(conf, INISEC_GLOBAL, opt, defval); + + return result; +} + /*! * Create volume struct * @@ -811,6 +841,8 @@ static struct vol *creatvol(AFPObj *obj, volume->v_preexec_close = 1; if (getoption_bool(obj->iniconfig, section, "root preexec close", preset, 0)) volume->v_root_preexec_close = 1; + if (vdgoption_bool(obj->iniconfig, section, "force xattr with sticky bit", preset, 0)) + volume->v_flags |= AFPVOL_FORCE_STICKY_XATTR; if ((val = getoption(obj->iniconfig, section, "ignored attributes", preset, obj->options.ignored_attr))) { if (strstr(val, "all")) { @@ -827,6 +859,19 @@ static struct vol *creatvol(AFPObj *obj, } } + val = getoption(obj->iniconfig, section, "chmod request", preset, NULL); + if (val == NULL) { + val = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "chmod request", "preserve"); + } + if (strcasecmp(val, "ignore") == 0) { + volume->v_flags |= AFPVOL_CHMOD_IGNORE; + } else if (strcasecmp(val, "preserve") == 0) { + volume->v_flags |= AFPVOL_CHMOD_PRESERVE_ACL; + } else if (strcasecmp(val, "simple") != 0) { + LOG(log_warning, logtype_afpd, "unknown 'chmod request' setting: '%s', using default", val); + volume->v_flags |= AFPVOL_CHMOD_PRESERVE_ACL; + } + /* * Handle read-only behaviour. semantics: * 1) neither the rolist nor the rwlist exist -> rw @@ -852,6 +897,8 @@ static struct vol *creatvol(AFPObj *obj, volume->v_ad_options |= ADVOL_FOLLO_SYML; if ((volume->v_flags & AFPVOL_RO)) volume->v_ad_options |= ADVOL_RO; + if ((volume->v_flags & AFPVOL_FORCE_STICKY_XATTR)) + volume->v_ad_options |= ADVOL_FORCE_STICKY_XATTR; /* Mac to Unix conversion flags*/ if ((volume->v_flags & AFPVOL_EILSEQ)) @@ -1000,14 +1047,45 @@ EC_CLEANUP: /* ---------------------- */ -static int volfile_changed(struct afp_options *p) +static int volfile_changed(AFPObj *obj) { struct stat st; + struct afp_options *p = &obj->options; + int result; + const char *includefile; + + result = stat(p->configfile, &st); + if (result != 0) { + LOG(log_debug, logtype_afpd, "where is the config file %s ?", + p->configfile); + /* + * We return 1 which means "config file changed". The caller + * will re-read config and fail too which is what we want. + */ + return 1; + } - if (!stat(p->configfile, &st) && st.st_mtime > p->volfile.mtime) { + if (st.st_mtime > p->volfile.mtime) { p->volfile.mtime = st.st_mtime; return 1; } + + includefile = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, + "include", NULL); + if (includefile) { + result = stat(includefile, &st); + if (result != 0) { + LOG(log_debug, logtype_afpd, "where is the include file %s ?", + includefile); + return 1; + } + + if (st.st_mtime > p->includefile.mtime) { + p->includefile.mtime = st.st_mtime; + return 1; + } + } + return 0; } @@ -1383,6 +1461,7 @@ int load_volumes(AFPObj *obj, lv_flags_t flags) struct stat st; int retries = 0; struct vol *vol; + char *includefile; LOG(log_debug, logtype_afpd, "load_volumes: BEGIN"); @@ -1403,7 +1482,7 @@ int load_volumes(AFPObj *obj, lv_flags_t flags) } if (Volumes) { - if (!volfile_changed(&obj->options)) + if (!volfile_changed(obj)) goto EC_CLEANUP; have_uservol = 0; for (vol = Volumes; vol; vol = vol->v_next) { @@ -1422,6 +1501,13 @@ int load_volumes(AFPObj *obj, lv_flags_t flags) LOG(log_debug, logtype_afpd, "load_volumes: no volumes yet"); EC_ZERO_LOG( lstat(obj->options.configfile, &st) ); obj->options.volfile.mtime = st.st_mtime; + + includefile = atalk_iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, + "include", NULL); + if (includefile) { + EC_ZERO_LOG( stat(includefile, &st) ); + obj->options.includefile.mtime = st.st_mtime; + } } /* try putting a read lock on the volume file twice, sleep 1 second if first attempt fails */ @@ -1600,36 +1686,18 @@ struct vol *getvolbypath(AFPObj *obj, const char *path) struct vol *tmp; const struct passwd *pw; char volname[AFPVOL_U8MNAMELEN + 1]; - char abspath[MAXPATHLEN + 1]; + char *realabspath = NULL; char volpath[MAXPATHLEN + 1], *realvolpath = NULL; char tmpbuf[MAXPATHLEN + 1]; const char *secname, *basedir, *p = NULL, *subpath = NULL, *subpathconfig; char *user = NULL, *prw; regmatch_t match[1]; - size_t abspath_len; LOG(log_debug, logtype_afpd, "getvolbypath(\"%s\")", path); - if (path[0] != '/') { - /* relative path, build absolute path */ - EC_NULL_LOG( getcwd(abspath, MAXPATHLEN) ); - strlcat(abspath, "/", MAXPATHLEN); - strlcat(abspath, path, MAXPATHLEN); - path = abspath; - } else { - strlcpy(abspath, path, MAXPATHLEN); - path = abspath; - } - /* path now points to a copy of path in the abspath buffer */ - - /* - * Strip trailing slashes - */ - abspath_len = strlen(abspath); - while (abspath[abspath_len - 1] == '/') { - abspath[abspath_len - 1] = 0; - abspath_len--; - } + /* build absolute path */ + EC_NULL( realabspath = realpath_safe(path) ); + path = realabspath; for (tmp = Volumes; tmp; tmp = tmp->v_next) { /* (1) */ size_t v_path_len = strlen(tmp->v_path); @@ -1751,6 +1819,8 @@ EC_CLEANUP: free(user); if (realvolpath) free(realvolpath); + if (realabspath) + free(realabspath); if (ret != 0) vol = NULL; return vol; @@ -1791,9 +1861,6 @@ int afp_config_parse(AFPObj *AFPObj, char *processname) options->configfile = AFPObj->cmdlineconfigfile ? strdup(AFPObj->cmdlineconfigfile) : strdup(_PATH_CONFDIR "afp.conf"); options->sigconffile = strdup(_PATH_STATEDIR "afp_signature.conf"); options->uuidconf = strdup(_PATH_STATEDIR "afp_voluuid.conf"); -#ifdef HAVE_TRACKER_SPARQL - options->slmod_path = strdup(_PATH_AFPDUAMPATH "slmod_sparql.so"); -#endif options->flags = OPTION_UUID | AFPObj->cmdlineflags; if ((config = atalk_iniparser_load(AFPObj->options.configfile)) == NULL) @@ -2083,9 +2150,6 @@ void afp_config_free(AFPObj *obj) CONFIG_ARG_FREE(obj->options.fqdn); if (obj->options.ignored_attr) CONFIG_ARG_FREE(obj->options.ignored_attr); - if (obj->options.slmod_path) - CONFIG_ARG_FREE(obj->options.slmod_path); - if (obj->options.unixcodepage) CONFIG_ARG_FREE(obj->options.unixcodepage); if (obj->options.maccodepage)