+ struct charset_functions *charset;
+ /* Codepages */
+
+ if (!volume->v_volcodepage)
+ volume->v_volcodepage = strdup("UTF8");
+
+ if ( (charset_t) -1 == ( volume->v_volcharset = add_charset(volume->v_volcodepage)) ) {
+ LOG (log_error, logtype_afpd, "Setting codepage %s as volume codepage failed", volume->v_volcodepage);
+ return -1;
+ }
+
+ if ( NULL == (charset = find_charset_functions(volume->v_volcodepage)) || charset->flags & CHARSET_ICONV ) {
+ LOG (log_warning, logtype_afpd, "WARNING: volume encoding %s is *not* supported by netatalk, expect problems !!!!", volume->v_volcodepage);
+ }
+
+ if (!volume->v_maccodepage)
+ volume->v_maccodepage = strdup(obj->options.maccodepage);
+
+ if ( (charset_t) -1 == ( volume->v_maccharset = add_charset(volume->v_maccodepage)) ) {
+ LOG (log_error, logtype_afpd, "Setting codepage %s as mac codepage failed", volume->v_maccodepage);
+ return -1;
+ }
+
+ if ( NULL == ( charset = find_charset_functions(volume->v_maccodepage)) || ! (charset->flags & CHARSET_CLIENT) ) {
+ LOG (log_error, logtype_afpd, "Fatal error: mac charset %s not supported", volume->v_maccodepage);
+ return -1;
+ }
+ volume->v_kTextEncoding = htonl(charset->kTextEncoding);
+ return 0;
+}
+
+/* ------------------------- */
+static int volume_openDB(struct vol *volume)
+{
+ int flags = 0;
+
+ if ((volume->v_flags & AFPVOL_NODEV)) {
+ 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);
+ }
+ if (volume->v_dbpath)
+ volume->v_cdb = cnid_open (volume->v_dbpath, volume->v_umask, volume->v_cnidscheme, flags);
+ else
+ volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, volume->v_cnidscheme, flags);
+
+ if (!volume->v_cdb) {
+ flags |= CNID_FLAG_MEMORY;
+ LOG(log_error, logtype_afpd, "Reopen volume %s using in memory temporary CNID DB.", volume->v_path);
+ volume->v_cdb = cnid_open (volume->v_path, volume->v_umask, "tdb", flags);
+#ifdef SERVERTEXT
+ /* kill ourself with SIGUSR2 aka msg pending */
+ if (volume->v_cdb) {
+ setmessage("Something wrong with the volume's DB ... FIXME with a better msg");
+ kill(getpid(), SIGUSR2);
+ /* XXX desactivate cachecnid ? */
+ }
+#endif
+ }
+
+ return (!volume->v_cdb)?-1:0;
+}
+
+/*
+ Check if the underlying filesystem supports EAs for ea:sys volumes.
+ If not, switch to ea:ad.
+ As we can't check (requires write access) on ro-volumes, we switch ea:auto
+ volumes that are options:ro to ea:none.
+*/
+static void check_ea_sys_support(struct vol *vol)
+{
+ uid_t process_uid = 0;
+ char eaname[] = {"org.netatalk.supports-eas.XXXXXX"};
+ const char *eacontent = "yes";
+
+ if (vol->v_vfs_ea == AFPVOL_EA_AUTO) {
+
+ if ((vol->v_flags & AFPVOL_RO) == AFPVOL_RO) {
+ LOG(log_info, logtype_logger, "read-only volume '%s', can't test for EA support, disabling EAs", vol->v_localname);
+ vol->v_vfs_ea = AFPVOL_EA_NONE;
+ return;
+ }
+
+ mktemp(eaname);
+
+ process_uid = geteuid();
+ if (process_uid)
+ if (seteuid(0) == -1) {
+ LOG(log_error, logtype_logger, "check_ea_sys_support: can't seteuid(0): %s", strerror(errno));
+ exit(EXITERR_SYS);
+ }
+
+ if ((sys_setxattr(vol->v_path, eaname, eacontent, 4, 0)) == 0) {
+ sys_removexattr(vol->v_path, eaname);
+ 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;
+ }
+
+ if (process_uid) {
+ if (seteuid(process_uid) == -1) {
+ LOG(log_error, logtype_logger, "can't seteuid back %s", strerror(errno));
+ exit(EXITERR_SYS);
+ }
+ }
+ }
+}
+
+/* -------------------------
+ * we are the user here
+ */
+int afp_openvol(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf, size_t *rbuflen)
+{
+ struct stat st;
+ char *volname;
+ char *p;
+
+ struct vol *volume;
+ struct dir *dir;
+ int len, ret;
+ size_t namelen;
+ u_int16_t bitmap;
+ char path[ MAXPATHLEN + 1];
+ char *vol_uname;
+ char *vol_mname;
+ char *volname_tmp;