]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/util/netatalk_conf.c
Fix CNID path for user homes
[netatalk.git] / libatalk / util / netatalk_conf.c
index e58f9a5fe5e47b927876222d74d1cdbeec05e7fd..fdb18f27e5cd2d1a3e113d9b24a89f99d502bc6d 100644 (file)
@@ -170,26 +170,28 @@ static char *get_vol_uuid(const AFPObj *obj, const char *volname)
   As we can't check (requires write access) on ro-volumes, we switch ea:auto
   volumes that are options:ro to ea:none.
 */
+#define EABUFSZ 4
 static int do_check_ea_support(const struct vol *vol)
 {
     int haseas;
-    char eaname[] = {"org.netatalk.supports-eas.XXXXXX"};
+    const char *eaname = "org.netatalk.has-Extended-Attributes";
     const char *eacontent = "yes";
+    char buf[EABUFSZ];
 
-    if ((vol->v_flags & AFPVOL_RO) == AFPVOL_RO) {
-        LOG(log_note, logtype_afpd, "read-only volume '%s', can't test for EA support, assuming yes", vol->v_localname);
+    if (sys_lgetxattr(vol->v_path, eaname, buf, EABUFSZ) != -1)
         return 1;
-    }
 
-    mktemp(eaname);
+    if (vol->v_flags & AFPVOL_RO) {
+        LOG(log_debug, logtype_afpd, "read-only volume '%s', can't test for EA support, assuming yes", vol->v_localname);
+        return 1;
+    }
 
     become_root();
 
-    if ((sys_setxattr(vol->v_path, eaname, eacontent, 4, 0)) == 0) {
-        sys_removexattr(vol->v_path, eaname);
+    if ((sys_setxattr(vol->v_path, eaname, eacontent, strlen(eacontent) + 1, 0)) == 0) {
         haseas = 1;
     } else {
-        LOG(log_warning, logtype_afpd, "volume \"%s\" does not support Extended Attributes or read-only volume root",
+        LOG(log_warning, logtype_afpd, "volume \"%s\" does not support Extended Attributes or read-only volume",
             vol->v_localname);
         haseas = 0;
     }
@@ -202,25 +204,14 @@ static int do_check_ea_support(const struct vol *vol)
 static void check_ea_support(struct vol *vol)
 {
     int haseas;
-    char eaname[] = {"org.netatalk.supports-eas.XXXXXX"};
-    const char *eacontent = "yes";
 
     haseas = do_check_ea_support(vol);
 
     if (vol->v_vfs_ea == AFPVOL_EA_AUTO) {
-        if ((vol->v_flags & AFPVOL_RO) == AFPVOL_RO) {
-            LOG(log_info, logtype_afpd, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname);
-            vol->v_vfs_ea = AFPVOL_EA_NONE;
-            return;
-        }
-
-        if (haseas) {
+        if (haseas)
             vol->v_vfs_ea = AFPVOL_EA_SYS;
-        } else {
-            LOG(log_warning, logtype_afpd, "volume \"%s\" does not support Extended Attributes, using ea:ad instead",
-                vol->v_localname);
-            vol->v_vfs_ea = AFPVOL_EA_AD;
-        }
+        else
+            vol->v_vfs_ea = AFPVOL_EA_NONE;
     }
 
     if (vol->v_adouble == AD_VERSION_EA) {
@@ -752,7 +743,7 @@ static struct vol *creatvol(AFPObj *obj,
     if (getoption_bool(obj->iniconfig, section, "acls", preset, 1))
         volume->v_flags |= AFPVOL_ACLS;
 #endif
-    if (!getoption_bool(obj->iniconfig, section, "convert adouble", preset, 1))
+    if (!getoption_bool(obj->iniconfig, section, "convert appledouble", preset, 1))
         volume->v_flags |= AFPVOL_NOV2TOEACONV;
 
     if (getoption_bool(obj->iniconfig, section, "preexec close", preset, 0))
@@ -765,12 +756,15 @@ static struct vol *creatvol(AFPObj *obj,
      * 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.
+     * 4) cnid scheme = last -> ro forcibly.
      */
     if (pwd) {
         if (accessvol(obj, getoption(obj->iniconfig, section, "rolist", preset, NULL), pwd->pw_name) == 1
             || accessvol(obj, getoption(obj->iniconfig, section, "rwlist", preset, NULL), pwd->pw_name) == 0)
             volume->v_flags |= AFPVOL_RO;
     }
+    if (0 == strcmp(volume->v_cnidscheme, "last"))
+        volume->v_flags |= AFPVOL_RO;
 
     if ((volume->v_flags & AFPVOL_NODEV))
         volume->v_ad_options |= ADVOL_NODEV;
@@ -992,8 +986,10 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
                 continue;
 
             /* check if user home matches our "basedir regex" */
-            if ((basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL)
+            if ((basedir = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "basedir regex", NULL)) == NULL) {
+                LOG(log_error, logtype_afpd, "\"basedir regex =\" must be defined in [Homes] section");
                 continue;
+            }
             LOG(log_debug, logtype_afpd, "readvolfile: basedir regex: '%s'", basedir);
 
             if (regexerr != 0 && (regexerr = regcomp(&reg, basedir, REG_EXTENDED)) != 0) {
@@ -1024,10 +1020,12 @@ static int readvolfile(AFPObj *obj, const struct passwd *pwent)
 
         /* do variable substitution for volume name */
         if (STRCMP(secname, ==, INISEC_HOMES)) {
-            if (p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home"))
-                strlcpy(tmp, p, MAXPATHLEN);
-            else
-                strlcpy(tmp, p, MAXPATHLEN);
+            p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home");
+            if (strstr(p, "$u") == NULL) {
+                LOG(log_warning, logtype_afpd, "home name must contain $u.");
+                p = "$u's home";
+            }
+            strlcpy(tmp, p, MAXPATHLEN);
         } else {
             strlcpy(tmp, secname, AFPVOL_U8MNAMELEN);
         }
@@ -1124,7 +1122,7 @@ int load_charset(struct vol *vol)
  * @param obj       (r) handle
  * @param delvol_fn (r) callback called for deleted volumes
  */
-int load_volumes(AFPObj *obj, void (*delvol_fn)(struct vol *))
+int load_volumes(AFPObj *obj, void (*delvol_fn)(const AFPObj *obj, struct vol *))
 {
     EC_INIT;
     int fd = -1;
@@ -1180,7 +1178,7 @@ int load_volumes(AFPObj *obj, void (*delvol_fn)(struct vol *))
         if (vol->v_deleted) {
             LOG(log_debug, logtype_afpd, "load_volumes: deleted: %s", vol->v_localname);
             if (delvol_fn)
-                delvol_fn(vol);
+                delvol_fn(obj, vol);
             vol = Volumes;
         }
     }
@@ -1335,7 +1333,7 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
         subpath = prw;
 
     strlcat(tmpbuf, user, MAXPATHLEN);
-    strlcat(obj->username, user, MAXUSERLEN);
+    strlcpy(obj->username, user, MAXUSERLEN);
     strlcat(tmpbuf, "/", MAXPATHLEN);
 
     /* (6) */
@@ -1359,6 +1357,8 @@ struct vol *getvolbypath(AFPObj *obj, const char *path)
 
     /* do variable substitution for volume name */
     p = iniparser_getstring(obj->iniconfig, INISEC_HOMES, "home name", "$u's home");
+    if (strstr(p, "$u") == NULL)
+        p = "$u's home";
     strlcpy(tmpbuf, p, AFPVOL_U8MNAMELEN);
     EC_NULL_LOG( volxlate(obj, volname, sizeof(volname) - 1, tmpbuf, pw, volpath, NULL) );
 
@@ -1426,8 +1426,6 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
     /* "server options" boolean options */
     if (!iniparser_getboolean(config, INISEC_GLOBAL, "zeroconf", 1))
         options->flags |= OPTION_NOZEROCONF;
-    if (iniparser_getboolean(config, INISEC_GLOBAL, "icon", 0))
-        options->flags |= OPTION_CUSTOMICON;
     if (iniparser_getboolean(config, INISEC_GLOBAL, "advertise ssh", 0))
         options->flags |= OPTION_ANNOUNCESSH;
     if (iniparser_getboolean(config, INISEC_GLOBAL, "map acls", 1))
@@ -1440,6 +1438,10 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
         options->flags |= OPTION_SERVERNOTIF;
     if (!iniparser_getboolean(config, INISEC_GLOBAL, "use sendfile", 1))
         options->flags |= OPTION_NOSENDFILE;
+    if (iniparser_getboolean(config, INISEC_GLOBAL, "solaris share reservations", 1))
+        options->flags |= OPTION_SHARE_RESERV;
+    if (iniparser_getboolean(config, INISEC_GLOBAL, "afp read locks", 0))
+        options->flags |= OPTION_AFP_READ_LOCK;
     if (!iniparser_getboolean(config, INISEC_GLOBAL, "save password", 1))
         options->passwdbits |= PASSWD_NOSAVE;
     if (iniparser_getboolean(config, INISEC_GLOBAL, "set password", 0))
@@ -1533,7 +1535,7 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
     /* unix charset is in [G] only */
     if (!(p = iniparser_getstring(config, INISEC_GLOBAL, "unix charset", NULL))) {
         options->unixcodepage = strdup("UTF8");
-        charset_names[CH_UNIX] = strdup("UTF8");
+        set_charset_name(CH_UNIX, "UTF8");
     } else {
         if (strcasecmp(p, "LOCALE") == 0) {
 #if defined(CODESET)
@@ -1549,7 +1551,7 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
             p = strdup("UTF8");
         }
         options->unixcodepage = strdup(p);
-        charset_names[CH_UNIX] = strdup(p);
+        set_charset_name(CH_UNIX, p);
     }
     options->unixcharset = CH_UNIX;
     LOG(log_debug, logtype_afpd, "Global unix charset is %s", options->unixcodepage);
@@ -1568,13 +1570,13 @@ int afp_config_parse(AFPObj *AFPObj, char *processname)
     /* mac charset is in [G] and [V] */
     if (!(p = iniparser_getstring(config, INISEC_GLOBAL, "mac charset", NULL))) {
         options->maccodepage = strdup("MAC_ROMAN");
-        charset_names[CH_MAC] = strdup("MAC_ROMAN");
+        set_charset_name(CH_MAC, "MAC_ROMAN");
     } else {
         if (strncasecmp(p, "MAC", 3) != 0) {
             LOG(log_warning, logtype_afpd, "Is '%s' really mac charset? ", p);
         }
         options->maccodepage = strdup(p);
-        charset_names[CH_MAC] = strdup(p);
+        set_charset_name(CH_MAC, p);
     }
     options->maccharset = CH_MAC;
     LOG(log_debug, logtype_afpd, "Global mac charset is %s", options->maccodepage);