📄 sysacls.c
字号:
return acl_d;}int sys_acl_clear_perms(SMB_ACL_PERMSET_T permset_d){ *permset_d = 0; return 0;}int sys_acl_add_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm){ if (perm != SMB_ACL_READ && perm != SMB_ACL_WRITE && perm != SMB_ACL_EXECUTE) { errno = EINVAL; return -1; } if (permset_d == NULL) { errno = EINVAL; return -1; } *permset_d |= perm; return 0;}int sys_acl_get_perm(SMB_ACL_PERMSET_T permset_d, SMB_ACL_PERM_T perm){ return *permset_d & perm;}char *sys_acl_to_text(SMB_ACL_T acl_d, ssize_t *len_p){ int i; int len, maxlen; char *text; /* * use an initial estimate of 20 bytes per ACL entry * when allocating memory for the text representation * of the ACL */ len = 0; maxlen = 20 * acl_d->count; if ((text = SMB_MALLOC(maxlen)) == NULL) { errno = ENOMEM; return NULL; } for (i = 0; i < acl_d->count; i++) { struct acl *ap = &acl_d->acl[i]; struct passwd *pw; struct group *gr; char tagbuf[12]; char idbuf[12]; char *tag; char *id = ""; char perms[4]; int nbytes; switch (ap->a_type) { /* * for debugging purposes it's probably more * useful to dump unknown tag types rather * than just returning an error */ default: slprintf(tagbuf, sizeof(tagbuf)-1, "0x%x", ap->a_type); tag = tagbuf; slprintf(idbuf, sizeof(idbuf)-1, "%ld", (long)ap->a_id); id = idbuf; break; case SMB_ACL_USER: id = uidtoname(ap->a_id); case SMB_ACL_USER_OBJ: tag = "user"; break; case SMB_ACL_GROUP: if ((gr = getgrgid(ap->a_id)) == NULL) { slprintf(idbuf, sizeof(idbuf)-1, "%ld", (long)ap->a_id); id = idbuf; } else { id = gr->gr_name; } case SMB_ACL_GROUP_OBJ: tag = "group"; break; case SMB_ACL_OTHER: tag = "other"; break; case SMB_ACL_MASK: tag = "mask"; break; } perms[0] = (ap->a_perm & SMB_ACL_READ) ? 'r' : '-'; perms[1] = (ap->a_perm & SMB_ACL_WRITE) ? 'w' : '-'; perms[2] = (ap->a_perm & SMB_ACL_EXECUTE) ? 'x' : '-'; perms[3] = '\0'; /* <tag> : <qualifier> : rwx \n \0 */ nbytes = strlen(tag) + 1 + strlen(id) + 1 + 3 + 1 + 1; /* * If this entry would overflow the buffer * allocate enough additional memory for this * entry and an estimate of another 20 bytes * for each entry still to be processed */ if ((len + nbytes) > maxlen) { char *oldtext = text; maxlen += nbytes + 20 * (acl_d->count - i); if ((text = SMB_REALLOC(oldtext, maxlen)) == NULL) { SAFE_FREE(oldtext); errno = ENOMEM; return NULL; } } slprintf(&text[len], nbytes-1, "%s:%s:%s\n", tag, id, perms); len += nbytes - 1; } if (len_p) *len_p = len; return text;}SMB_ACL_T sys_acl_init(int count){ SMB_ACL_T a; if (count < 0) { errno = EINVAL; return NULL; } /* * note that since the definition of the structure pointed * to by the SMB_ACL_T includes the first element of the * acl[] array, this actually allocates an ACL with room * for (count+1) entries */ if ((a = SMB_MALLOC(sizeof(struct SMB_ACL_T) + count * sizeof(struct acl))) == NULL) { errno = ENOMEM; return NULL; } a->size = count + 1; a->count = 0; a->next = -1; return a;}int sys_acl_create_entry(SMB_ACL_T *acl_p, SMB_ACL_ENTRY_T *entry_p){ SMB_ACL_T acl_d; SMB_ACL_ENTRY_T entry_d; if (acl_p == NULL || entry_p == NULL || (acl_d = *acl_p) == NULL) { errno = EINVAL; return -1; } if (acl_d->count >= acl_d->size) { errno = ENOSPC; return -1; } entry_d = &acl_d->acl[acl_d->count++]; entry_d->a_type = 0; entry_d->a_id = -1; entry_d->a_perm = 0; *entry_p = entry_d; return 0;}int sys_acl_set_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T tag_type){ switch (tag_type) { case SMB_ACL_USER: case SMB_ACL_USER_OBJ: case SMB_ACL_GROUP: case SMB_ACL_GROUP_OBJ: case SMB_ACL_OTHER: case SMB_ACL_MASK: entry_d->a_type = tag_type; break; default: errno = EINVAL; return -1; } return 0;}int sys_acl_set_qualifier(SMB_ACL_ENTRY_T entry_d, void *qual_p){ if (entry_d->a_type != SMB_ACL_GROUP && entry_d->a_type != SMB_ACL_USER) { errno = EINVAL; return -1; } entry_d->a_id = *((id_t *)qual_p); return 0;}int sys_acl_set_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T permset_d){ if (*permset_d & ~(SMB_ACL_READ|SMB_ACL_WRITE|SMB_ACL_EXECUTE)) { return EINVAL; } entry_d->a_perm = *permset_d; return 0;}/* * sort the ACL and check it for validity * * if it's a minimal ACL with only 4 entries then we * need to recalculate the mask permissions to make * sure that they are the same as the GROUP_OBJ * permissions as required by the UnixWare acl() system call. * * (note: since POSIX allows minimal ACLs which only contain * 3 entries - ie there is no mask entry - we should, in theory, * check for this and add a mask entry if necessary - however * we "know" that the caller of this interface always specifies * a mask so, in practice "this never happens" (tm) - if it *does* * happen aclsort() will fail and return an error and someone will * have to fix it ...) */static int acl_sort(SMB_ACL_T acl_d){ int fixmask = (acl_d->count <= 4); if (aclsort(acl_d->count, fixmask, acl_d->acl) != 0) { errno = EINVAL; return -1; } return 0;} int sys_acl_valid(SMB_ACL_T acl_d){ return acl_sort(acl_d);}int sys_acl_set_file(const char *name, SMB_ACL_TYPE_T type, SMB_ACL_T acl_d){ struct stat s; struct acl *acl_p; int acl_count; struct acl *acl_buf = NULL; int ret; if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { errno = EINVAL; return -1; } if (acl_sort(acl_d) != 0) { return -1; } acl_p = &acl_d->acl[0]; acl_count = acl_d->count; /* * if it's a directory there is extra work to do * since the acl() system call will replace both * the access ACLs and the default ACLs (if any) */ if (stat(name, &s) != 0) { return -1; } if (S_ISDIR(s.st_mode)) { SMB_ACL_T acc_acl; SMB_ACL_T def_acl; SMB_ACL_T tmp_acl; int i; if (type == SMB_ACL_TYPE_ACCESS) { acc_acl = acl_d; def_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_DEFAULT); } else { def_acl = acl_d; acc_acl = tmp_acl = sys_acl_get_file(name, SMB_ACL_TYPE_ACCESS); } if (tmp_acl == NULL) { return -1; } /* * allocate a temporary buffer for the complete ACL */ acl_count = acc_acl->count + def_acl->count; acl_p = acl_buf = SMB_MALLOC_ARRAY(struct acl, acl_count); if (acl_buf == NULL) { sys_acl_free_acl(tmp_acl); errno = ENOMEM; return -1; } /* * copy the access control and default entries into the buffer */ memcpy(&acl_buf[0], &acc_acl->acl[0], acc_acl->count * sizeof(acl_buf[0])); memcpy(&acl_buf[acc_acl->count], &def_acl->acl[0], def_acl->count * sizeof(acl_buf[0])); /* * set the ACL_DEFAULT flag on the default entries */ for (i = acc_acl->count; i < acl_count; i++) { acl_buf[i].a_type |= ACL_DEFAULT; } sys_acl_free_acl(tmp_acl); } else if (type != SMB_ACL_TYPE_ACCESS) { errno = EINVAL; return -1; } ret = acl(name, SETACL, acl_count, acl_p); SAFE_FREE(acl_buf); return ret;}int sys_acl_set_fd(int fd, SMB_ACL_T acl_d){ if (acl_sort(acl_d) != 0) { return -1; } return facl(fd, SETACL, acl_d->count, &acl_d->acl[0]);}int sys_acl_delete_def_file(const char *path){ SMB_ACL_T acl_d; int ret; /* * fetching the access ACL and rewriting it has * the effect of deleting the default ACL */ if ((acl_d = sys_acl_get_file(path, SMB_ACL_TYPE_ACCESS)) == NULL) { return -1; } ret = acl(path, SETACL, acl_d->count, acl_d->acl); sys_acl_free_acl(acl_d); return ret;}int sys_acl_free_text(char *text){ SAFE_FREE(text); return 0;}int sys_acl_free_acl(SMB_ACL_T acl_d) { SAFE_FREE(acl_d); return 0;}int sys_acl_free_qualifier(void *qual, SMB_ACL_TAG_T tagtype){ return 0;}#elif defined(HAVE_HPUX_ACLS)#include <dl.h>/* * Based on the Solaris/SCO code - with modifications. *//* * Note that while this code implements sufficient functionality * to support the sys_acl_* interfaces it does not provide all * of the semantics of the POSIX ACL interfaces. * * In particular, an ACL entry descriptor (SMB_ACL_ENTRY_T) returned * from a call to sys_acl_get_entry() should not be assumed to be * valid after calling any of the following functions, which may * reorder the entries in the ACL. * * sys_acl_valid() * sys_acl_set_file() * sys_acl_set_fd() *//* This checks if the POSIX ACL system call is defined *//* which basically corresponds to whether JFS 3.3 or *//* higher is installed. If acl() was called when it *//* isn't defined, it causes the process to core dump *//* so it is important to check this and avoid acl() *//* calls if it isn't there. */static BOOL hpux_acl_call_presence(void){ shl_t handle = NULL; void *value; int ret_val=0; static BOOL already_checked=0; if(already_checked) return True; ret_val = shl_findsym(&handle, "acl", TYPE_PROCEDURE, &value); if(ret_val != 0) { DEBUG(5, ("hpux_acl_call_presence: shl_findsym() returned %d, errno = %d, error %s\n", ret_val, errno, strerror(errno))); DEBUG(5,("hpux_acl_call_presence: acl() system call is not present. Check if you have JFS 3.3 and above?\n")); return False; } DEBUG(10,("hpux_acl_call_presence: acl() system call is present. We have JFS 3.3 or above \n")); already_checked = True; return True;}int sys_acl_get_entry(SMB_ACL_T acl_d, int entry_id, SMB_ACL_ENTRY_T *entry_p){ if (entry_id != SMB_ACL_FIRST_ENTRY && entry_id != SMB_ACL_NEXT_ENTRY) { errno = EINVAL; return -1; } if (entry_p == NULL) { errno = EINVAL; return -1; } if (entry_id == SMB_ACL_FIRST_ENTRY) { acl_d->next = 0; } if (acl_d->next < 0) { errno = EINVAL; return -1; } if (acl_d->next >= acl_d->count) { return 0; } *entry_p = &acl_d->acl[acl_d->next++]; return 1;}int sys_acl_get_tag_type(SMB_ACL_ENTRY_T entry_d, SMB_ACL_TAG_T *type_p){ *type_p = entry_d->a_type; return 0;}int sys_acl_get_permset(SMB_ACL_ENTRY_T entry_d, SMB_ACL_PERMSET_T *permset_p){ *permset_p = &entry_d->a_perm; return 0;}void *sys_acl_get_qualifier(SMB_ACL_ENTRY_T entry_d){ if (entry_d->a_type != SMB_ACL_USER && entry_d->a_type != SMB_ACL_GROUP) { errno = EINVAL; return NULL; } return &entry_d->a_id;}/* * There is no way of knowing what size the ACL returned by * ACL_GET will be unless you first call ACL_CNT which means * making an additional system call. * * In the hope of avoiding the cost of the additional system * call in most cases, we initially allocate enough space for * an ACL with INITIAL_ACL_SIZE entries. If this turns out to * be too small then we use ACL_CNT to find out the actual * size, reallocate the ACL buffer, and then call ACL_GET again. */#define INITIAL_ACL_SIZE 16SMB_ACL_T sys_acl_get_file(const char *path_p, SMB_ACL_TYPE_T type){ SMB_ACL_T acl_d; int count; /* # of ACL entries allocated */ int naccess; /* # of access ACL entries */ int ndefault; /* # of default ACL entries */ if(hpux_acl_call_presence() == False) { /* Looks like we don't have the acl() system call on HPUX. * May be the system doesn't have the latest version of JFS. */ return NULL; } if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) { errno = EINVAL; return NULL; } count = INITIAL_ACL_SIZE; if ((acl_d = sys_acl_init(count)) == NULL) { return NULL; } /* * If there isn't enough space for the ACL entries we use * ACL_CNT to determine the actual number of ACL entries * reallocate and try again. This is in a loop because it * is possible that someone else could modify the ACL and * increase the number of entries between the call to * ACL_CNT and the call to ACL_GET. */ while ((count = acl(path_p, ACL_GET, count, &acl_d->acl[0])) < 0 && errno == ENOSPC) { sys_acl_free_acl(acl_d); if ((count = acl(path_p, ACL_CNT, 0, NULL)) < 0) { return NULL; }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -