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
}
Example #2
0
/**
* 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;
}