static void clone_spawn(void)
{
  l r;
  if(ps_n<ps_max){
    r=clone(SIGCHLD,0,0,0,0);
    if(ISERR(r)){
      PERR("FATAL:error cloning %ld\n",r);
      kill(0,SIGTERM);
      exit(-1);
    }
    if(r==0) goto clone_entry_setup;
 
    ++ps_n;
  }
  return;

clone_entry_setup:
  do r=close(0); while(r==-EINTR);//for the connexion socket
  do r=close(1); while(r==-EINTR);//for the connexion socket
  //keep stderr

  do r=close(sigs_fd); while(r==-EINTR);//don't care of parent signal
  do r=close(epfd); while(r==-EINTR);//don't use parent epoll

  clone_entry();
  return;
}
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
}
示例#3
0
int
do_set(
	const char *path_p,
	const struct stat *st,
	const seq_t seq)
{
	acl_t old_acl = NULL, old_default_acl = NULL;
	acl_t acl = NULL, default_acl = NULL;
	acl_t *xacl, *old_xacl;
	acl_entry_t ent;
	cmd_t cmd;
	int which_entry;
	int errors = 0, error;
	char *acl_text;
	int acl_modified = 0, default_acl_modified = 0;
	int acl_mask_provided = 0, default_acl_mask_provided = 0;

	/* Execute the commands in seq (read ACLs on demand) */
	error = seq_get_cmd(seq, SEQ_FIRST_CMD, &cmd);
	if (error == 0)
		return 0;
	while (error == 1) {
		if (cmd->c_type == ACL_TYPE_ACCESS) {
			xacl = &acl;
			old_xacl = &old_acl;
			acl_modified = 1;
			if (cmd->c_tag == ACL_MASK)
				acl_mask_provided = 1;
		} else {
			xacl = &default_acl;
			old_xacl = &old_default_acl;
			default_acl_modified = 1;
			if (cmd->c_tag == ACL_MASK)
				default_acl_mask_provided = 1;
		}

		RETRIEVE_ACL(cmd->c_type);

		/* Check for `X', and replace with `x' as appropriate. */
		if (cmd->c_perm & CMD_PERM_COND_EXECUTE) {
			cmd->c_perm &= ~CMD_PERM_COND_EXECUTE;
			if (S_ISDIR(st->st_mode) || has_execute_perms(*xacl))
				cmd->c_perm |= CMD_PERM_EXECUTE;
		}

		switch(cmd->c_cmd) {
			case CMD_ENTRY_REPLACE:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (!ent) {
					if (acl_create_entry(xacl, &ent) != 0)
						goto fail;
					acl_set_tag_type(ent, cmd->c_tag);
					if (cmd->c_id != ACL_UNDEFINED_ID)
						acl_set_qualifier(ent,
								  &cmd->c_id);
				}
				set_perm(ent, cmd->c_perm, ~cmd->c_perm);
				break;

			case CMD_ENTRY_ADD:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (ent)
					set_perm(ent, cmd->c_perm, 0);
				break;

			case CMD_ENTRY_SUBTRACT:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (ent)
					set_perm(ent, 0, cmd->c_perm);
				break;

			case CMD_REMOVE_ENTRY:
				ent = find_entry(*xacl, cmd->c_tag, cmd->c_id);
				if (ent)
					acl_delete_entry(*xacl, ent);
				else
					/* ignore */;
				break;

			case CMD_REMOVE_EXTENDED_ACL:
				remove_extended_entries(acl);
				break;

			case CMD_REMOVE_ACL:
				acl_free(*xacl);
				*xacl = acl_init(5);
				if (!*xacl)
					goto fail;
				break;

			default:
				errno = EINVAL;
				goto fail;
		}

		error = seq_get_cmd(seq, SEQ_NEXT_CMD, &cmd);
	}

	if (error < 0)
		goto fail;

	/* Try to fill in missing entries */
	if (default_acl && acl_entries(default_acl) != 0) {
		xacl = &acl;
		old_xacl = &old_acl;
	
		if (!find_entry(default_acl, ACL_USER_OBJ, ACL_UNDEFINED_ID)) {
			if (!acl)
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
			clone_entry(acl, ACL_USER_OBJ,
			            &default_acl, ACL_USER_OBJ);
		}
		if (!find_entry(default_acl, ACL_GROUP_OBJ, ACL_UNDEFINED_ID)) {
			if (!acl)
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
			clone_entry(acl, ACL_GROUP_OBJ,
			            &default_acl, ACL_GROUP_OBJ);
		}
		if (!find_entry(default_acl, ACL_OTHER, ACL_UNDEFINED_ID)) {
			if (!acl)
				RETRIEVE_ACL(ACL_TYPE_ACCESS);
			clone_entry(acl, ACL_OTHER,
			            &default_acl, ACL_OTHER);
		}
	}

	/* update mask entries and check if ACLs are valid */
	if (acl && acl_modified) {
		if (acl_equiv_mode(acl, NULL) != 0) {
			if (!acl_mask_provided &&
			    !find_entry(acl, ACL_MASK, ACL_UNDEFINED_ID))
				clone_entry(acl, ACL_GROUP_OBJ,
				            &acl, ACL_MASK);
			if (opt_recalculate != -1 &&
			    (!acl_mask_provided || opt_recalculate == 1))
				acl_calc_mask(&acl);
		}

		error = acl_check(acl, &which_entry);
		if (error < 0)
			goto fail;
		if (error > 0) {
			acl_text = acl_to_any_text(acl, NULL, ',', 0);
			fprintf(stderr, gettext("%s: %s: Malformed access ACL "
				"`%s': %s at entry %d\n"), progname, path_p,
				acl_text, acl_error(error), which_entry+1);
			acl_free(acl_text);
			errors++;
			goto cleanup;
		}
	}

	if (default_acl && acl_entries(default_acl) != 0 &&
	    default_acl_modified) {
		if (acl_equiv_mode(default_acl, NULL) != 0) {
			if (!default_acl_mask_provided &&
			    !find_entry(default_acl,ACL_MASK,ACL_UNDEFINED_ID))
				clone_entry(default_acl, ACL_GROUP_OBJ,
				            &default_acl, ACL_MASK);
			if (opt_recalculate != -1 &&
			    (!default_acl_mask_provided ||
			     opt_recalculate == 1))
				acl_calc_mask(&default_acl);
		}

		error = acl_check(default_acl, &which_entry);
		if (error < 0)
			goto fail;
		if (error > 0) {
			acl_text = acl_to_any_text(default_acl, NULL, ',', 0);
			fprintf(stderr, gettext("%s: %s: Malformed default ACL "
			                  "`%s': %s at entry %d\n"),
				progname, path_p, acl_text,
				acl_error(error), which_entry+1);
			acl_free(acl_text);
			errors++;
			goto cleanup;
		}
	}

	/* Only directores can have default ACLs */
	if (default_acl && !S_ISDIR(st->st_mode) && opt_recursive) {
		/* In recursive mode, ignore default ACLs for files */
		acl_free(default_acl);
		default_acl = NULL;
	}

	/* check which ACLs have changed */
	if (acl && old_acl && acl_cmp(old_acl, acl) == 0) {
		acl_free(acl);
		acl = NULL;
	}
	if ((default_acl && old_default_acl &&
	    acl_cmp(old_default_acl, default_acl) == 0)) {
		acl_free(default_acl);
		default_acl = NULL;
	}

	/* update the file system */
	if (opt_test) {
		print_test(stdout, path_p, st,
		           acl, default_acl);
		goto cleanup;
	}
	if (acl) {
		if (acl_set_file(path_p, ACL_TYPE_ACCESS, acl) != 0) {
			if (errno == ENOSYS || errno == ENOTSUP) {
				int saved_errno = errno;
				mode_t mode;

				if (acl_equiv_mode(acl, &mode) != 0) {
					errno = saved_errno;
					goto fail;
				} else if (chmod(path_p, mode) != 0)
					goto fail;
			} else
				goto fail;
		}
	}
	if (default_acl) {
		if (S_ISDIR(st->st_mode)) {
			if (acl_entries(default_acl) == 0) {
				if (acl_delete_def_file(path_p) != 0 &&
				    errno != ENOSYS && errno != ENOTSUP)
					goto fail;
			} else {
				if (acl_set_file(path_p, ACL_TYPE_DEFAULT,
						 default_acl) != 0)
					goto fail;
			}
		} else {
			if (acl_entries(default_acl) != 0) {
				fprintf(stderr, gettext(
						"%s: %s: Only directories "
						"can have default ACLs\n"),
					progname, path_p);
				errors++;
				goto cleanup;
			}
		}
	}

	error = 0;

cleanup:
	if (acl)
		acl_free(acl);
	if (old_acl)
		acl_free(old_acl);
	if (default_acl)
		acl_free(default_acl);
	if (old_default_acl)
		acl_free(old_default_acl);
	return errors;
	
fail:
	fprintf(stderr, "%s: %s: %s\n", progname, path_p, strerror(errno));
	errors++;
	goto cleanup;
}