X-Git-Url: https://arthur.barton.de/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=libatalk%2Futil%2Fnetatalk_conf.c;h=a08ddebd44dafacaf84a7d8b87fc735e627392a3;hb=be799718387d2e6029cccee369b25ba85bb2fade;hp=26c80f112e4812b86b51ec953d21492c533bab7b;hpb=b3c52ea7097b09cafe6002acca2c996f1f5ea2fb;p=netatalk.git diff --git a/libatalk/util/netatalk_conf.c b/libatalk/util/netatalk_conf.c index 26c80f11..a08ddebd 100644 --- a/libatalk/util/netatalk_conf.c +++ b/libatalk/util/netatalk_conf.c @@ -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) { @@ -571,8 +562,8 @@ static struct vol *creatvol(AFPObj *obj, { EC_INIT; struct vol *volume = NULL; - int suffixlen, vlen, tmpvlen, u8mvlen, macvlen; - char tmpname[AFPVOL_U8MNAMELEN+1]; + int i, suffixlen, vlen, tmpvlen, u8mvlen, macvlen; + char *tmpname; ucs2_t u8mtmpname[(AFPVOL_U8MNAMELEN+1)*2], mactmpname[(AFPVOL_MACNAMELEN+1)*2]; char suffix[6]; /* max is #FFFF */ uint16_t flags; @@ -651,9 +642,14 @@ static struct vol *creatvol(AFPObj *obj, else EC_NULL( volume->v_maccodepage = strdup(obj->options.maccodepage) ); + vlen = strlen(name); + tmpname = strdup(name); + for(i = 0; i < vlen; i++) + if(tmpname[i] == '/') tmpname[i] = ':'; + bstring dbpath; EC_NULL_LOG( val = iniparser_getstring(obj->iniconfig, INISEC_GLOBAL, "vol dbpath", _PATH_STATEDIR "CNID/") ); - EC_NULL_LOG( dbpath = bformat("%s/%s/", val, name) ); + EC_NULL_LOG( dbpath = bformat("%s/%s/", val, tmpname) ); EC_NULL_LOG( volume->v_dbpath = strdup(bdata(dbpath)) ); bdestroy(dbpath); @@ -752,7 +748,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 +761,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; @@ -801,12 +800,9 @@ static struct vol *creatvol(AFPObj *obj, /* because v_vid has not been decided yet. */ suffixlen = sprintf(suffix, "#%X", lastvid + 1 ); - - vlen = strlen( name ); - /* Unicode Volume Name */ /* Firstly convert name from unixcharset to UTF8-MAC */ - flags = CONV_IGNORE; + flags = CONV_IGNORE | CONV_ALLOW_SLASH; tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags); if (tmpvlen <= 0) { strcpy(tmpname, "???"); @@ -816,7 +812,7 @@ static struct vol *creatvol(AFPObj *obj, /* Do we have to mangle ? */ if ( (flags & CONV_REQMANGLE) || (tmpvlen > obj->options.volnamelen)) { if (tmpvlen + suffixlen > obj->options.volnamelen) { - flags = CONV_FORCE; + flags = CONV_FORCE | CONV_ALLOW_SLASH; tmpvlen = convert_charset(obj->options.unixcharset, CH_UTF8_MAC, 0, name, vlen, tmpname, obj->options.volnamelen - suffixlen, &flags); tmpname[tmpvlen >= 0 ? tmpvlen : 0] = 0; } @@ -832,7 +828,7 @@ static struct vol *creatvol(AFPObj *obj, /* Maccharset Volume Name */ /* Firsty convert name from unixcharset to maccharset */ - flags = CONV_IGNORE; + flags = CONV_IGNORE | CONV_ALLOW_SLASH; tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, name, vlen, tmpname, AFPVOL_U8MNAMELEN, &flags); if (tmpvlen <= 0) { strcpy(tmpname, "???"); @@ -842,7 +838,7 @@ static struct vol *creatvol(AFPObj *obj, /* Do we have to mangle ? */ if ( (flags & CONV_REQMANGLE) || (tmpvlen > AFPVOL_MACNAMELEN)) { if (tmpvlen + suffixlen > AFPVOL_MACNAMELEN) { - flags = CONV_FORCE; + flags = CONV_FORCE | CONV_ALLOW_SLASH; tmpvlen = convert_charset(obj->options.unixcharset, obj->options.maccharset, 0, @@ -897,16 +893,16 @@ static struct vol *creatvol(AFPObj *obj, initvol_vfs(volume); /* get/store uuid from file in afpd master*/ - if (!(pwd) && (volume->v_flags & AFPVOL_TM)) { - char *uuid = get_vol_uuid(obj, volume->v_localname); - if (!uuid) { - LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID", - volume->v_localname); - } else { - volume->v_uuid = uuid; - LOG(log_debug, logtype_afpd, "Volume '%s': UUID '%s'", - volume->v_localname, volume->v_uuid); - } + become_root(); + char *uuid = get_vol_uuid(obj, volume->v_localname); + unbecome_root(); + if (!uuid) { + LOG(log_error, logtype_afpd, "Volume '%s': couldn't get UUID", + volume->v_localname); + } else { + volume->v_uuid = uuid; + LOG(log_debug, logtype_afpd, "Volume '%s': UUID '%s'", + volume->v_localname, volume->v_uuid); } /* no errors shall happen beyond this point because the cleanup would mess the volume chain up */ @@ -992,8 +988,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(®, basedir, REG_EXTENDED)) != 0) { @@ -1024,10 +1022,16 @@ 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"; + } + if (strchr(p, ':') != NULL) { + LOG(log_warning, logtype_afpd, "home name must not contain \":\"."); + p = "$u's home"; + } + strlcpy(tmp, p, MAXPATHLEN); } else { strlcpy(tmp, secname, AFPVOL_U8MNAMELEN); } @@ -1124,7 +1128,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 +1184,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 +1339,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 +1363,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) ); @@ -1404,11 +1410,14 @@ int afp_config_parse(AFPObj *AFPObj, char *processname) char *q, *r; char val[MAXVAL]; + if (processname != NULL) + set_processname(processname); + AFPObj->afp_version = 11; 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"); - options->flags = OPTION_ACL2MACCESS | OPTION_UUID | OPTION_SERVERNOTIF | AFPObj->cmdlineflags; + options->flags = OPTION_UUID | AFPObj->cmdlineflags; if ((config = iniparser_load(AFPObj->options.configfile)) == NULL) return -1; @@ -1418,16 +1427,11 @@ int afp_config_parse(AFPObj *AFPObj, char *processname) options->logconfig = iniparser_getstrdup(config, INISEC_GLOBAL, "log level", "default:note"); options->logfile = iniparser_getstrdup(config, INISEC_GLOBAL, "log file", NULL); - if (processname[0] != '\0') { - set_processname(processname); - setuplog(options->logconfig, options->logfile); - } + setuplog(options->logconfig, options->logfile); /* "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)) @@ -1436,10 +1440,14 @@ int afp_config_parse(AFPObj *AFPObj, char *processname) options->flags |= OPTION_KEEPSESSIONS; if (iniparser_getboolean(config, INISEC_GLOBAL, "close vol", 0)) options->flags |= OPTION_CLOSEVOL; - if (!iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 1)) + if (!iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 0)) 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 +1541,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 +1557,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 +1576,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);