-
-
Save hiroyuki-sato/30ab25ad72047c1cfe31 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/* | |
3月 05 00:48:03.541107 afpd[15411] {vfs.c:426} (E:Default): acl_set_file(vol->ad_path(path, ADFLAGS_HF), type, acl) failed: そのようなファイルやディレクトリはありません | |
3月 05 00:48:03.541162 afpd[15411] {acls.c:1333} (E:Default): vol->vfs->vfs_acl(vol, name, ACL_TYPE_ACCESS, 0, access_acl) failed: そのようなファイルやディレクトリはありません | |
3月 05 00:48:03.541197 afpd[15411] {acls.c:1730} (W:AFPDaemon): afp_setacl("/home/public/600282_376817112382006_1219774923_n.jpg"): error | |
ea = sys クライアント側のEAをサーバ側のEAに保存 | |
ea = ad クライアント側のEAをサーバ側の.AppleDoubleディレクトリに保存 | |
ea = auto sysがダメだったらadにフォールバック | |
ea = none EAをサポートせず | |
appledouble = ea FinderInfo,TimeStamp,ResourceFork類をサーバ側のEAに保存 | |
appledouble = v2 FinderInfo,TimeStamp,ResourceFork類をサーバ側の.AppleDouble | |
ディレクトリに保存 | |
*/ | |
// | |
// etc/afpd/acls.c | |
// | |
int afp_setacl(AFPObj *obj, char *ibuf, size_t ibuflen _U_, char *rbuf _U_, size_t *rbuflen) | |
{ | |
struct vol *vol; | |
struct dir *dir; | |
int ret; | |
uint32_t did; | |
uint16_t vid, bitmap; | |
struct path *s_path; | |
LOG(log_debug9, logtype_afpd, "afp_setacl: BEGIN"); | |
*rbuflen = 0; | |
ibuf += 2; | |
/* .... */ | |
/* Start processing request */ | |
/* Change owner: dont even try */ | |
if (bitmap & kFileSec_UUID) { | |
LOG(log_note, logtype_afpd, "afp_setacl: change owner request, discarded"); | |
ret = AFPERR_ACCESS; | |
ibuf += UUID_BINSIZE; | |
} | |
/* Change group: certain changes might be allowed, so try it. FIXME: not implemented yet. */ | |
if (bitmap & kFileSec_UUID) { | |
LOG(log_note, logtype_afpd, "afp_setacl: change group request, not supported"); | |
ret = AFPERR_PARAM; | |
ibuf += UUID_BINSIZE; | |
} | |
/* Remove ACL ? */ | |
if (bitmap & kFileSec_REMOVEACL) { | |
LOG(log_debug, logtype_afpd, "afp_setacl: Remove ACL request."); | |
if ((ret = remove_acl(vol, s_path->u_name, S_ISDIR(s_path->st.st_mode))) != AFP_OK) | |
LOG(log_error, logtype_afpd, "afp_setacl: error from remove_acl"); | |
} | |
/* Change ACL ? */ | |
if (bitmap & kFileSec_ACL) { | |
LOG(log_debug, logtype_afpd, "afp_setacl: Change ACL request."); | |
/* Get no of ACEs the client put on the wire */ | |
uint32_t ace_count; | |
memcpy(&ace_count, ibuf, sizeof(uint32_t)); | |
ace_count = htonl(ace_count); | |
ibuf += 8; /* skip ACL flags (see acls.h) */ | |
ret = set_acl(vol, | |
s_path->u_name, | |
(bitmap & kFileSec_Inherit), | |
(darwin_ace_t *)ibuf, | |
ace_count); | |
if (ret == 0) | |
ret = AFP_OK; | |
else { | |
LOG(log_warning, logtype_afpd, "afp_setacl(\"%s/%s\"): error", | |
getcwdpath(), s_path->u_name); | |
ret = AFPERR_MISC; | |
} | |
} | |
LOG(log_debug9, logtype_afpd, "afp_setacl: END"); | |
return ret; | |
} | |
// etc/afpd/acls.c | |
static int set_acl(const struct vol *vol, | |
const char *name, | |
int inherit _U_, | |
darwin_ace_t *daces, | |
uint32_t ace_count) | |
{ | |
EC_INIT; | |
struct stat st; | |
acl_t default_acl = NULL; | |
acl_t access_acl = NULL; | |
acl_entry_t entry; | |
acl_tag_t tag; | |
int entry_id = ACL_FIRST_ENTRY; | |
/* flags to indicate if the object has a minimal default acl and/or an extended | |
* default acl. | |
*/ | |
uint32_t default_acl_flags = 0; | |
LOG(log_maxdebug, logtype_afpd, "set_acl: BEGIN"); | |
EC_NULL_LOG_ERR(access_acl = acl_get_file(name, ACL_TYPE_ACCESS), AFPERR_MISC); | |
/* Iterate through acl and remove all extended acl entries. */ | |
while (acl_get_entry(access_acl, entry_id, &entry) == 1) { | |
entry_id = ACL_NEXT_ENTRY; | |
EC_ZERO_LOG(acl_get_tag_type(entry, &tag)); | |
if ((tag == ACL_USER) || (tag == ACL_GROUP) || (tag == ACL_MASK)) { | |
EC_ZERO_LOG_ERR(acl_delete_entry(access_acl, entry), AFPERR_MISC); | |
} | |
} /* while */ | |
/* In case we are acting on a directory prepare a default acl. For files default_acl will be NULL. | |
* If the directory already has a default acl it will be preserved. | |
*/ | |
EC_ZERO_LOG_ERR(lstat(name, &st), AFPERR_NOOBJ); | |
if (S_ISDIR(st.st_mode)) { | |
default_acl = acl_get_file(name, ACL_TYPE_DEFAULT); | |
if (default_acl) { | |
/* If default_acl is not empty then the dir has a default acl. */ | |
if (acl_get_entry(default_acl, ACL_FIRST_ENTRY, &entry) == 1) | |
default_acl_flags = HAS_DEFAULT_ACL; | |
acl_free(default_acl); | |
} | |
default_acl = acl_dup(access_acl); | |
} | |
/* adds the clients aces */ | |
EC_ZERO_ERR(map_aces_darwin_to_posix(daces, &default_acl, &access_acl, ace_count, &default_acl_flags), AFPERR_MISC); | |
/* calcuate ACL mask */ | |
EC_ZERO_LOG_ERR(acl_calc_mask(&access_acl), AFPERR_MISC); | |
/* is it ok? */ | |
EC_ZERO_LOG_ERR(acl_valid(access_acl), AFPERR_MISC); | |
/* set it */ | |
EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_ACCESS, access_acl), AFPERR_MISC); | |
EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_ACCESS, 0, access_acl), AFPERR_MISC); | |
if (default_acl) { | |
/* If the dir has an extended default acl it's ACL_MASK must be updated.*/ | |
if (default_acl_flags & HAS_EXT_DEFAULT_ACL) | |
EC_ZERO_LOG_ERR(acl_calc_mask(&default_acl), AFPERR_MISC); | |
if (default_acl_flags) { | |
EC_ZERO_LOG_ERR(acl_valid(default_acl), AFPERR_MISC); | |
EC_ZERO_LOG_ERR(acl_set_file(name, ACL_TYPE_DEFAULT, default_acl), AFPERR_MISC); | |
EC_ZERO_LOG_ERR(vol->vfs->vfs_acl(vol, name, ACL_TYPE_DEFAULT, 0, default_acl), AFPERR_MISC); | |
} | |
} | |
EC_CLEANUP: | |
if (access_acl) acl_free(access_acl); | |
if (default_acl) acl_free(default_acl); | |
LOG(log_maxdebug, logtype_afpd, "set_acl: END"); | |
EC_EXIT; | |
} | |
#endif /* HAVE_POSIX_ACLS */ | |
#ifdef HAVE_POSIX_ACLS | |
#define VFS_FUNC_ARGS_ACL const struct vol *vol, const char *path, acl_type_t type, int count, acl_t acl | |
#define VFS_FUNC_VARS_ACL vol, path, type, count, acl | |
#endif | |
#ifdef HAVE_POSIX_ACLS | |
static int RF_posix_acl(VFS_FUNC_ARGS_ACL) | |
{ | |
EC_INIT; | |
static char buf[ MAXPATHLEN + 1]; | |
struct stat st; | |
int len; | |
if (stat(path, &st) == -1) | |
EC_FAIL; | |
if (S_ISDIR(st.st_mode)) { | |
len = snprintf(buf, MAXPATHLEN, "%s/.AppleDouble",path); | |
if (len < 0 || len >= MAXPATHLEN) | |
EC_FAIL; | |
/* set acl on .AppleDouble dir first */ | |
EC_ZERO_LOG(acl_set_file(buf, type, acl)); | |
if (type == ACL_TYPE_ACCESS) | |
/* set ACL on ressource fork (".Parent") too */ | |
EC_ZERO_LOG(acl_set_file(vol->ad_path(path, ADFLAGS_DIR), type, acl)); | |
} else { | |
/* set ACL on ressource fork */ | |
EC_ZERO_LOG(acl_set_file(vol->ad_path(path, ADFLAGS_HF), type, acl)); | |
} | |
EC_CLEANUP: | |
if (ret != 0) | |
return AFPERR_MISC; | |
return AFP_OK; | |
} | |
// libatalk/util/netatalk_conf.c | |
/* | |
Check if the underlying filesystem supports EAs. | |
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. | |
*/ | |
#define EABUFSZ 4 | |
static int do_check_ea_support(const struct vol *vol) | |
{ | |
int haseas; | |
const char *eaname = "org.netatalk.has-Extended-Attributes"; | |
const char *eacontent = "yes"; | |
char buf[EABUFSZ]; | |
if (sys_lgetxattr(vol->v_path, eaname, buf, EABUFSZ) != -1) | |
return 1; | |
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, strlen(eacontent) + 1, 0)) == 0) { | |
haseas = 1; | |
} else { | |
LOG(log_warning, logtype_afpd, "volume \"%s\" does not support Extended Attributes or read-only volume", | |
vol->v_localname); | |
haseas = 0; | |
} | |
unbecome_root(); | |
return haseas; | |
} | |
static void check_ea_support(struct vol *vol) | |
{ | |
int haseas; | |
haseas = do_check_ea_support(vol); | |
if (vol->v_vfs_ea == AFPVOL_EA_AUTO) { | |
if (haseas) | |
vol->v_vfs_ea = AFPVOL_EA_SYS; | |
else | |
vol->v_vfs_ea = AFPVOL_EA_NONE; | |
} | |
if (vol->v_adouble == AD_VERSION_EA) { | |
if (!haseas) | |
vol->v_adouble = AD_VERSION2; | |
} | |
} | |
// etc/afpd/volume.c | |
static int getvolparams(const AFPObj *obj, uint16_t bitmap, struct vol *vol, struct stat *st, char *buf, size_t *buflen) | |
{ | |
/* ...*/ | |
case VOLPBIT_ATTR : | |
ashort = 0; | |
/* check for read-only. | |
* NOTE: we don't actually set the read-only flag unless | |
* it's passed in that way as it's possible to mount | |
* a read-write filesystem under a read-only one. */ | |
if ((vol->v_flags & AFPVOL_RO) || | |
((utime(vol->v_path, NULL) < 0) && (errno == EROFS))) { | |
ashort |= VOLPBIT_ATTR_RO; | |
} | |
/* prior 2.1 only VOLPBIT_ATTR_RO is defined */ | |
if (obj->afp_version > 20) { | |
if (vol->v_cdb != NULL && (vol->v_cdb->flags & CNID_FLAG_PERSISTENT)) | |
ashort |= VOLPBIT_ATTR_FILEID; | |
ashort |= VOLPBIT_ATTR_CATSEARCH; | |
if (obj->afp_version >= 30) { | |
ashort |= VOLPBIT_ATTR_UTF8; | |
if (vol->v_flags & AFPVOL_UNIX_PRIV) | |
ashort |= VOLPBIT_ATTR_UNIXPRIV; | |
if (vol->v_flags & AFPVOL_TM) | |
ashort |= VOLPBIT_ATTR_TM; | |
if (vol->v_flags & AFPVOL_NONETIDS) | |
ashort |= VOLPBIT_ATTR_NONETIDS; | |
if (obj->afp_version >= 32) { | |
if (vol->v_vfs_ea) | |
ashort |= VOLPBIT_ATTR_EXT_ATTRS; | |
if (vol->v_flags & AFPVOL_ACLS) | |
ashort |= VOLPBIT_ATTR_ACLS; | |
} | |
} | |
} | |
ashort = htons(ashort); | |
memcpy(data, &ashort, sizeof( ashort )); | |
data += sizeof( ashort ); | |
break; | |
// libatalk/vfs/vfs.c | |
/* ---------------- */ | |
void initvol_vfs(struct vol *vol) | |
{ | |
vol->vfs = &vfs_master_funcs; | |
/* Default adouble stuff */ | |
if (vol->v_adouble == AD_VERSION2) { | |
vol->vfs_modules[0] = &netatalk_adouble_v2; | |
vol->ad_path = ad_path; | |
} else { | |
vol->vfs_modules[0] = &netatalk_adouble_ea; | |
#ifdef HAVE_EAFD | |
vol->ad_path = ad_path_ea; | |
#else | |
vol->ad_path = ad_path_osx; | |
#endif | |
} | |
/* Extended Attributes */ | |
if (vol->v_vfs_ea == AFPVOL_EA_SYS) { | |
LOG(log_debug, logtype_afpd, "initvol_vfs: enabling EA support with native EAs"); | |
vol->vfs_modules[1] = &netatalk_ea_sys; | |
} else if (vol->v_vfs_ea == AFPVOL_EA_AD) { | |
LOG(log_debug, logtype_afpd, "initvol_vfs: enabling EA support with adouble files"); | |
vol->vfs_modules[1] = &netatalk_ea_adouble; | |
} else { | |
LOG(log_debug, logtype_afpd, "initvol_vfs: volume without EA support"); | |
} | |
/* ACLs */ | |
#ifdef HAVE_SOLARIS_ACLS | |
vol->vfs_modules[2] = &netatalk_solaris_acl_adouble; | |
#endif | |
#ifdef HAVE_POSIX_ACLS | |
vol->vfs_modules[2] = &netatalk_posix_acl_adouble; | |
#endif | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment