* FIX: Opening files without metadata EA may result in an invalid
metadata EA. Check for malformed metadata EAs and delete them.
Fixes bug #510.
-
+* FIX: Fix an issue with filenames containing non-ASCII characters that
+ lead to a failure setting the size of a files ressource fork.
+ This affected application like Adobe Photoshop where saving
+ files may fail. Fixes bug #511.
+* UPD: Enhance ACL mapping, change global ACL option 'map acl' to take
+ the following options: "none", "rights" (default), "mode".
+ none = no mapping, this resembles the previous false/no setting
+ rights = map ACLs to Finder UARights, this resembles the previous
+ true/yes setting. This is the default.
+ mode = map ACLs to Finder UARights and UNIX mode
+ From FR #73.
+
Changes in 3.0.3
================
* UPD: afpd: Increase default DSI server quantum to 1 MB
*
* @param obj (r) handle
* @param path (r) path to filesystem object
- * @param sb (r) struct stat of path
- * @param result (w) resulting Darwin allow ACE
+ * @param sb (rw) struct stat of path
+ * @param ma (rw) UARights struct
+ * @param rights_out (w) mapped Darwin ACL rights
*
* @returns 0 or -1 on error
*/
static int solaris_acl_rights(const AFPObj *obj,
const char *path,
- const struct stat *sb,
- uint32_t *result)
+ struct stat *sb,
+ struct maccess *ma,
+ uint32_t *rights_out)
{
EC_INIT;
int i, ace_count, checkgroup;
darwin_rights |= nfsv4_to_darwin_rights[i].to;
}
- *result |= darwin_rights;
+ LOG(log_maxdebug, logtype_afpd, "rights: 0x%08x", darwin_rights);
+
+ if (rights_out)
+ *rights_out = darwin_rights;
+
+ if (ma && obj->options.flags & OPTION_ACL2MACCESS) {
+ if (darwin_rights & DARWIN_ACE_READ_DATA)
+ ma->ma_user |= AR_UREAD;
+ if (darwin_rights & DARWIN_ACE_WRITE_DATA)
+ ma->ma_user |= AR_UWRITE;
+ if (darwin_rights & (DARWIN_ACE_EXECUTE | DARWIN_ACE_SEARCH))
+ ma->ma_user |= AR_USEARCH;
+ }
+
+ if (sb && obj->options.flags & OPTION_ACL2MODE) {
+ if (darwin_rights & DARWIN_ACE_READ_DATA)
+ sb->st_mode |= S_IRUSR;
+ if (darwin_rights & DARWIN_ACE_WRITE_DATA)
+ sb->st_mode |= S_IWUSR;
+ if (darwin_rights & (DARWIN_ACE_EXECUTE | DARWIN_ACE_SEARCH))
+ sb->st_mode |= S_IXUSR;
+ }
EC_CLEANUP:
if (aces) free(aces);
break;
}
}
- /* apply the mask and adjust user and group permissions */
- ma->ma_user |= (acl_rights & mask);
- ma->ma_group = (group_rights & mask);
- /* update st_mode to properly reflect group permissions */
- sb->st_mode &= ~S_IRWXG;
-
- if (ma->ma_group & AR_USEARCH)
- sb->st_mode |= S_IXGRP;
-
- if (ma->ma_group & AR_UWRITE)
- sb->st_mode |= S_IWGRP;
+ if (obj->options.flags & OPTION_ACL2MACCESS) {
+ /* apply the mask and adjust user and group permissions */
+ ma->ma_user |= (acl_rights & mask);
+ ma->ma_group = (group_rights & mask);
+ }
- if (ma->ma_group & AR_UREAD)
- sb->st_mode |= S_IRGRP;
+ if (obj->options.flags & OPTION_ACL2MODE) {
+ /* update st_mode to properly reflect group permissions */
+ sb->st_mode &= ~S_IRWXG;
+ if (ma->ma_group & AR_USEARCH)
+ sb->st_mode |= S_IXGRP;
+ if (ma->ma_group & AR_UWRITE)
+ sb->st_mode |= S_IWGRP;
+ if (ma->ma_group & AR_UREAD)
+ sb->st_mode |= S_IRGRP;
+ }
EC_CLEANUP:
if (acl) acl_free(acl);
LOG(log_debug, logtype_afpd, "check_access: allowed rights from dircache: 0x%08x", allowed_rights);
} else {
#ifdef HAVE_SOLARIS_ACLS
- EC_ZERO_LOG(solaris_acl_rights(obj, path, &st, &allowed_rights));
+ EC_ZERO_LOG(solaris_acl_rights(obj, path, &st, NULL, &allowed_rights));
#endif
#ifdef HAVE_POSIX_ACLS
EC_ZERO_LOG(posix_acl_rights(obj, path, &st, &allowed_rights));
EC_ZERO_LOG_ERR(lstat(cfrombstr(parent), &st), AFPERR_MISC);
#ifdef HAVE_SOLARIS_ACLS
- EC_ZERO_LOG(solaris_acl_rights(obj, cfrombstr(parent), &st, &parent_rights));
+ EC_ZERO_LOG(solaris_acl_rights(obj, cfrombstr(parent), &st, NULL, &parent_rights));
#endif
#ifdef HAVE_POSIX_ACLS
EC_ZERO_LOG(posix_acl_rights(obj, path, &st, &parent_rights));
{
EC_INIT;
- if ( ! (obj->options.flags & OPTION_ACL2MACCESS)
+ if ( ! (obj->options.flags & (OPTION_ACL2MACCESS | OPTION_ACL2MODE))
|| ! (vol->v_flags & AFPVOL_ACLS))
return 0;
getcwdpath(), path, ma->ma_user);
#ifdef HAVE_SOLARIS_ACLS
- uint32_t rights = 0;
- EC_ZERO_LOG(solaris_acl_rights(obj, path, st, &rights));
-
- LOG(log_maxdebug, logtype_afpd, "rights: 0x%08x", rights);
-
- if (rights & DARWIN_ACE_READ_DATA)
- ma->ma_user |= AR_UREAD;
- if (rights & DARWIN_ACE_WRITE_DATA)
- ma->ma_user |= AR_UWRITE;
- if (rights & (DARWIN_ACE_EXECUTE | DARWIN_ACE_SEARCH))
- ma->ma_user |= AR_USEARCH;
+ EC_ZERO_LOG(solaris_acl_rights(obj, path, st, ma, NULL));
#endif
#ifdef HAVE_POSIX_ACLS
goto afp_setfork_err;
}
- err = ad_rtruncate(ofork->of_ad, size);
+ err = ad_rtruncate(ofork->of_ad, mtoupath(ofork->of_vol, of_name(ofork), ofork->of_did, utf8_encoding(obj)), size);
if (st_size > size)
ad_tmplock(ofork->of_ad, eid, ADLOCK_CLR, size, st_size -size, ofork->of_refnum);
if (err < 0)
int ad_reso_refcount;
off_t ad_rlen; /* ressource fork len with AFP 3.0 *
* the header parameter size is too small. */
- char *ad_name; /* name in server encoding (usually UTF8) */
+ char *ad_name; /* name (UTF8-MAC) */
struct adouble_fops *ad_ops;
uint16_t ad_open_forks; /* open forks (by others) */
char ad_data[AD_DATASZ_MAX];
extern ssize_t adf_pread(struct ad_fd *, void *, size_t, off_t);
extern ssize_t adf_pwrite(struct ad_fd *, const void *, size_t, off_t);
extern int ad_dtruncate(struct adouble *, off_t);
-extern int ad_rtruncate(struct adouble *, off_t);
+extern int ad_rtruncate(struct adouble *, const char *, off_t);
extern int copy_fork(int eid, struct adouble *add, struct adouble *ads);
/* ad_size.c */
#define OPTION_UUID (1 << 7)
#define OPTION_ACL2MACCESS (1 << 8)
#define OPTION_NOZEROCONF (1 << 9)
+#define OPTION_ACL2MODE (1 << 10)
#define OPTION_SHARE_RESERV (1 << 11) /* whether to use Solaris fcntl F_SHARE locks */
#define OPTION_DBUS_AFPSTATS (1 << 12) /* whether to run dbus thread for afpstats */
#define OPTION_SPOTLIGHT (1 << 13) /* whether to enable Spotlight support */
}
/* ------------------------ */
-int ad_rtruncate( struct adouble *ad, const off_t size)
+int ad_rtruncate(struct adouble *ad, const char *uname, const off_t size)
{
EC_INIT;
#ifndef HAVE_EAFD
if (ad->ad_vers == AD_VERSION_EA && size == 0)
- EC_NEG1( unlink(ad->ad_ops->ad_path(ad->ad_name, 0)) );
+ EC_NEG1( unlink(ad->ad_ops->ad_path(uname, 0)) );
else
#endif
EC_NEG1( sys_ftruncate(ad_reso_fileno(ad), size + ad->ad_eid[ ADEID_RFORK ].ade_off) );
ad->ad_rlen = size;
else
LOG(log_error, logtype_ad, "ad_rtruncate(\"%s\"): %s",
- fullpathname(ad->ad_name), strerror(errno));
+ fullpathname(uname), strerror(errno));
EC_EXIT;
}
options->flags |= OPTION_NOZEROCONF;
if (iniparser_getboolean(config, INISEC_GLOBAL, "advertise ssh", 0))
options->flags |= OPTION_ANNOUNCESSH;
- if (iniparser_getboolean(config, INISEC_GLOBAL, "map acls", 1))
- options->flags |= OPTION_ACL2MACCESS;
if (iniparser_getboolean(config, INISEC_GLOBAL, "close vol", 0))
options->flags |= OPTION_CLOSEVOL;
if (!iniparser_getboolean(config, INISEC_GLOBAL, "client polling", 0))
options->disconnected = iniparser_getint (config, INISEC_GLOBAL, "disconnect time",24);
options->tracker_loglevel = iniparser_getint (config, INISEC_GLOBAL, "tracker loglevel", 1);
+ p = iniparser_getstring(config, INISEC_GLOBAL, "map acls", "rights");
+ if (STRCMP(p, ==, "rights"))
+ options->flags |= OPTION_ACL2MACCESS;
+ else if (STRCMP(p, ==, "mode"))
+ options->flags |= OPTION_ACL2MODE | OPTION_ACL2MACCESS;
+ else {
+ if (STRCMP(p, !=, "none")) {
+ LOG(log_error, logtype_afpd, "bad ACL mapping option: %s, defaulting to 'rights'", p);
+ options->flags |= OPTION_ACL2MACCESS;
+ }
+ }
+
if ((p = iniparser_getstring(config, INISEC_GLOBAL, "hostname", NULL))) {
EC_NULL_LOG( options->hostname = strdup(p) );
} else {