MateVFSResult file_set_acl (const char *path, const MateVFSFileInfo *info, MateVFSContext *context) { #ifdef HAVE_SOLARIS_ACL GList *acls; GList *entry; guint len; MateVFSResult re; aclent_t *new_aclp; aclent_t *taclp; guint aclp_i; gboolean changed; if (info->acl == NULL) return MATE_VFS_ERROR_BAD_PARAMETERS; acls = mate_vfs_acl_get_ace_list (info->acl); if (acls == NULL) return MATE_VFS_OK; changed = fixup_acl (info->acl, acls); if (changed) { mate_vfs_acl_free_ace_list (acls); acls = mate_vfs_acl_get_ace_list (info->acl); if (acls == NULL) return MATE_VFS_OK; } len = g_list_length (acls); if (len <= 0) return MATE_VFS_OK; new_aclp = (aclent_t *) malloc (len * sizeof(aclent_t)); if (new_aclp == NULL) return MATE_VFS_ERROR_NO_MEMORY; memset (new_aclp, 0, len * sizeof(aclent_t)); aclp_i = 0; taclp = new_aclp; for (entry=acls; entry != NULL; entry = entry->next) { MateVFSACE *ace = MATE_VFS_ACE(entry->data); re = translate_ace_into_aclent (ace, taclp); if (re != MATE_VFS_OK) continue; aclp_i++; taclp++; } /* Sort it out */ re = aclsort (aclp_i, 0, (aclent_t *)new_aclp); if (re == -1) { g_free (new_aclp); return MATE_VFS_ERROR_INTERNAL; } /* Commit it to the file system */ re = acl (path, SETACL, aclp_i, (aclent_t *)new_aclp); if (re < 0) { int err = errno; g_free (new_aclp); return aclerrno_to_vfserror(err); } g_free (new_aclp); return MATE_VFS_OK; #elif defined(HAVE_POSIX_ACL) GList *acls; GList *entry; acl_t acl_obj; acl_t acl_obj_default; if (info->acl == NULL) return MATE_VFS_ERROR_BAD_PARAMETERS; /* POSIX ACL object */ acl_obj_default = acl_get_file (path, ACL_TYPE_DEFAULT); acl_obj = acl_get_file (path, ACL_TYPE_ACCESS); if (acl_obj == NULL) return MATE_VFS_ERROR_GENERIC; /* Parse stored information */ acls = mate_vfs_acl_get_ace_list (info->acl); if (acls == NULL) return MATE_VFS_OK; for (entry=acls; entry != NULL; entry = entry->next) { MateVFSACE *ace = MATE_VFS_ACE(entry->data); gboolean is_default = FALSE; const char *id_str; MateVFSACLKind kind; int id; int re; acl_tag_t type; mode_t perms = 0; acl_entry_t new_entry = NULL; acl_permset_t permset = NULL; id_str = mate_vfs_ace_get_id (ace); kind = mate_vfs_ace_get_kind (ace); is_default = mate_vfs_ace_get_inherit (ace); /* Perms */ if (mate_vfs_ace_check_perm (ace, MATE_VFS_ACL_READ)) perms |= CMD_PERM_READ; else if (mate_vfs_ace_check_perm (ace, MATE_VFS_ACL_WRITE)) perms |= CMD_PERM_WRITE; else if (mate_vfs_ace_check_perm (ace, MATE_VFS_ACL_EXECUTE)) perms |= CMD_PERM_EXECUTE; /* Type */ switch (kind) { case MATE_VFS_ACL_USER: id = string_to_uid (id_str); type = ACL_USER; break; case MATE_VFS_ACL_GROUP: id = string_to_gid (id_str); type = ACL_GROUP; break; case MATE_VFS_ACL_OTHER: type = ACL_OTHER; break; default: return MATE_VFS_ERROR_NOT_SUPPORTED; } /* Add the entry */ new_entry = find_entry (acl_obj, type, id); if (new_entry == NULL) { /* new */ if (is_default) re = acl_create_entry (&acl_obj_default, &new_entry); else re = acl_create_entry (&acl_obj, &new_entry); if (re != 0) return aclerrno_to_vfserror (errno); /* e_tag */ re = acl_set_tag_type (new_entry, type); if (re != 0) return aclerrno_to_vfserror (errno); /* e_id */ re = acl_set_qualifier (new_entry, &id); if (re != 0) return aclerrno_to_vfserror (errno); } /* e_perm */ re = acl_get_permset (new_entry, &permset); if (re != 0) return aclerrno_to_vfserror (errno); set_permset (permset, perms); /* Fix it up */ if (is_default && (acl_obj_default != NULL)) { if (! find_entry (acl_obj_default, ACL_USER_OBJ, ACL_UNDEFINED_ID)) { clone_entry (acl_obj, ACL_USER_OBJ, &acl_obj_default, ACL_USER_OBJ); } if (! find_entry (acl_obj_default, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) { clone_entry (acl_obj, ACL_GROUP_OBJ, &acl_obj_default, ACL_GROUP_OBJ); } if (! find_entry (acl_obj_default, ACL_OTHER, ACL_UNDEFINED_ID)) { clone_entry (acl_obj, ACL_OTHER, &acl_obj_default, ACL_OTHER); } } if (acl_equiv_mode (acl_obj, NULL) != 0) { if (! find_entry (acl_obj, ACL_MASK, ACL_UNDEFINED_ID)) { clone_entry (acl_obj, ACL_GROUP_OBJ, &acl_obj, ACL_MASK); } if (is_default) re = acl_calc_mask (&acl_obj_default); else re = acl_calc_mask (&acl_obj); if (re != 0) return aclerrno_to_vfserror (errno); } } mate_vfs_acl_free_ace_list (acls); return MATE_VFS_OK; #else return MATE_VFS_ERROR_NOT_SUPPORTED; #endif }
/** * parsing short-form acl string * acl_string: acl entries string in short form * string_size: len of acl_string * acl_part: ptr to acl_entry_part to fill * errno: sets errno to EINVAL if string is malformed, or ENOMEM if no more entries available * errno is also set by getuidfromname and getgidfromname * returns: status and sets errno **/ _BOOL acl_short_parse(const char* acl_string,size_t string_size, acl_entry_part *acl_part){ if( string_size<=0 ||acl_string==NULL || *acl_string == '\0' ) return FALSE; if(strlen(acl_string)!=string_size) return FALSE; //copy over the string char acl_string_copy[string_size+1]; strncpy(acl_string_copy,acl_string,string_size); acl_string_copy[string_size]= '\0'; char * acl_string_cpy = acl_string_copy; //need ptr arithmetic volatile acl_entry_in *current_entry = NULL; char *qual_str = NULL; //loop through short form acl string for(;*acl_string_cpy!='\0';acl_string_cpy++){ if(*acl_string_cpy==',') continue; //set the tag switch (*acl_string_cpy++) { case 'u': //since we don't know if a qual is specified, we just set to OBJ for now if(*acl_string_cpy++!=':') {errno = EINVAL; return FALSE;} acl_entry_in *user_entry = NULL; qual_str = acl_string_cpy; if(*qual_str!=':'){ while(*qual_str!=':'){ // keep moving till we find a ':' or '\0' if(*qual_str++ == '\0'){errno = EINVAL; return FALSE;} } *qual_str='\0'; user_entry =&acl_part->user[acl_part->num_users++]; //convert the qualifier name to uid (reason we added '\0') if((user_entry->qualifier.u_qual=getuidfromname(acl_string_cpy))==-1){ if(errno ==0){ errno = ENOENT; return FALSE; } } *qual_str=':'; acl_string_cpy = qual_str+1; user_entry->tag = ACL_USER; } else{ acl_string_cpy++; user_entry = &acl_part->user_obj; user_entry->qualifier.u_obj_qual = USER_OBJ_QUAL; user_entry->tag = ACL_USER_OBJ; } if(!set_permset(&acl_string_cpy,user_entry)){ errno=EINVAL; return FALSE;} break; case 'g': //same reason for 'u' if(*acl_string_cpy++!=':') {errno = EINVAL; return FALSE;} acl_entry_in *group_entry = NULL; qual_str = acl_string_cpy; if(*qual_str!=':'){ while(*qual_str!=':'){ // keep moving till we find a ':' or '\0' if(*qual_str++ == '\0'){errno = EINVAL; return FALSE;} } *qual_str='\0'; group_entry =&acl_part->group[acl_part->num_groups++]; //convert the qualifier name to uid (reason we added '\0') if((group_entry->qualifier.g_qual=getgidfromname(acl_string_cpy))==-1){ if(errno ==0){ errno = ENOENT; return FALSE; } } *qual_str=':'; acl_string_cpy = qual_str+1; group_entry->tag = ACL_GROUP; } else{ acl_string_cpy++; group_entry = &acl_part->group_obj; group_entry->qualifier.g_obj_qual = GROUP_OBJ_QUAL; group_entry->tag = ACL_GROUP_OBJ; } if(!set_permset(&acl_string_cpy,group_entry)){errno = EINVAL; return FALSE;} break; case 'o': // other if(*acl_string_cpy++!=':'||*acl_string_cpy++!=':') {errno = EINVAL; return FALSE;} acl_part->other.qualifier.o_qual = OTHER_QUAL; acl_part->other.tag = ACL_OTHER; if(!set_permset(&acl_string_cpy,&acl_part->other)){errno = EINVAL; return FALSE;} break; case 'm': //mask if(*acl_string_cpy++!=':'||*acl_string_cpy++!=':') {errno = EINVAL; return FALSE;} acl_part->mask.qualifier.m_qual = MASK_QUAL; acl_part->mask.tag = ACL_MASK; if(!set_permset(&acl_string_cpy,&acl_part->mask)){errno = EINVAL; return FALSE;} break; default: // it is something unknown errno = EINVAL; return FALSE; break; } } return TRUE; }