[Cvs-nserver-commits] CVS: cvs-nserver/acl dir-acl.c,1.1.2.19,1.1.2.20
Brought to you by:
tyranny
From: Alexey M. <ty...@us...> - 2002-06-09 00:12:41
|
Update of /cvsroot/cvs-nserver/cvs-nserver/acl In directory usw-pr-cvs1:/tmp/cvs-serv1826 Modified Files: Tag: NCLI-1-11-1 dir-acl.c Log Message: Refactor, document, and fix create_and_load_dir_acl(), create_dir_acl(), and destroy_dir_acl() Index: dir-acl.c =================================================================== RCS file: /cvsroot/cvs-nserver/cvs-nserver/acl/Attic/dir-acl.c,v retrieving revision 1.1.2.19 retrieving revision 1.1.2.20 diff -u -d -r1.1.2.19 -r1.1.2.20 --- dir-acl.c 8 Jun 2002 23:30:00 -0000 1.1.2.19 +++ dir-acl.c 9 Jun 2002 00:12:39 -0000 1.1.2.20 @@ -9,9 +9,7 @@ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - Copyright (c) Alexey Mahotkin <al...@hs...> 2001 - - Per-directory ACL implementation + Copyright (c) Alexey Mahotkin <al...@hs...> 2001-2002 */ @@ -20,32 +18,32 @@ \brief Directory-level ACL implementation. - Directory-level permissions are kept in the DIRACL file in each + Directory-level permissions are kept in the \c DIRACL file in each subdirectory where at list one ACE (access control list entry) exists. - DIRACL file is a plain text file. Each line starts with a single + \c DIRACL file is a plain text file. Each line starts with a single letter, indicating type of this line. There are currently two types of lines: - - "/" line contains directory-level access control entry; + - \c "/" line contains directory-level access control entry; - - "D" line contains default file access control entry; + - \c "D" line contains default file access control entry; The initial letter is followed by several tab-separated fields. Directory-level ACE lines contain the following fields: - - name of the branch (or "<trunk>"); + - name of the branch (or \c "trunk"); - name of the user to whom this ACE is applied; - directory permission string; - Directory permission strings contain either single word "none", + Directory permission strings contain either single word \c "none", meaning no permission, or a sequence of one or more comma-separated - words "access" or "modify" with obvious meaning (see the + words \c "access" or \c "modify" with obvious meaning (see the Administrator's Guide for more details). */ @@ -90,14 +88,16 @@ static char *current_toplevel_directory = "./"; /*! \fn void set_toplevel_directory (char* toplevel_directory); + \brief Sets the toplevel directory (most often this is a path to repository) + \param toplevel_directory Path to toplevel directory. ACLs are handled only for directories within this toplevel - directory. The get_dir_acl() function will return NULL if asked + directory. The get_dir_acl() function will return \c NULL if asked about directory which is not within toplevel directory. - Initial value is "./". + Initial value is \c "./". */ @@ -128,14 +128,14 @@ return current_default_dir_perm; } -static DIR_ACL *create_and_load_dir_acl (char *dir, char *branch); +static DIR_ACL *create_and_load_dir_acl (char *dir); static DIR_ACL *internal_get_dir_acl (char *dir, char *branch, struct DIR_ACL *the_dir_acl); DIR_ACL * get_dir_acl (char *dir, char *branch) { - struct DIR_ACL *dir_acl = create_and_load_dir_acl(dir, branch); + struct DIR_ACL *dir_acl = create_and_load_dir_acl(dir); char *dir_copy = strdup(dir); if (dir_copy == NULL) return NULL; @@ -196,7 +196,7 @@ last_component = strrchr(dir + toplevel_len, '/'); if (last_component == NULL) { /* we are processing the top dir */ - struct DIR_ACL *topdir_acl = create_and_load_dir_acl(dir, branch); + struct DIR_ACL *topdir_acl = create_and_load_dir_acl(dir); add_dir_to_path(the_dir_acl, topdir_acl); @@ -204,7 +204,7 @@ /* we need to strip the last component and try to get its top dir */ struct DIR_ACL *this_dir_acl; *last_component = '\0'; - this_dir_acl = create_and_load_dir_acl(dir, branch); + this_dir_acl = create_and_load_dir_acl(dir); add_dir_to_path(the_dir_acl, this_dir_acl); internal_get_dir_acl(dir, branch, the_dir_acl); @@ -215,24 +215,24 @@ } +/*! \fn struct DIR_ACL* create_dir_acl (char* dir) -#define MAX_LINE_SIZE 128 + \brief Creates empty struct DIR_ACL for the specified directory. -static DIR_ACL * -create_and_load_dir_acl (char *dir, char *branch) -{ - FILE *acl; - struct DIR_ACL *dir_acl; - struct stat stat_buf; - struct stringbuf *filename; - char buf[MAX_LINE_SIZE]; + \param dir Full path do directory - errno = 0; + \retval "struct DIR_ACL*" containing empty ACL for this directory - if (stat(dir, &stat_buf) == -1) - return NULL; + \retval NULL if memory allocation failed. - dir_acl = (DIR_ACL *) calloc(1, sizeof(struct DIR_ACL)); + \internal + + */ + +static struct DIR_ACL* +create_dir_acl (char* dir) +{ + struct DIR_ACL* dir_acl = calloc(1, sizeof(struct DIR_ACL)); if (dir_acl == NULL) return NULL; @@ -242,16 +242,73 @@ return NULL; } + return dir_acl; +} + + +static void +destroy_dir_acl (struct DIR_ACL* dir_acl) +{ + if (!dir_acl) + return; + + free_stringbuf(dir_acl->dirname); + free(dir_acl); +} + + + +#define MAX_LINE_SIZE 128 + +/*! \fn struct DIR_ACL* create_and_load_dir_acl (char* dir) + + \brief Creates struct DIR_ACL for specified directory and loads its + access control list. + + \param dir Full path to a directory + + \retval "struct DIR_ACL*" containing ACL for this directory + + \retval NULL if: + - memory allocation failed; + - specified directory does not exist (\c errno is set to \c ENOENT); + - too long line in the DIRACL file (\c errno is set to \c E2BIG); + - invalid line format in the DIRACL file (\c errno is set to \c EINVAL); + + */ + +static struct DIR_ACL * +create_and_load_dir_acl (char *dir) +{ + FILE *acl = NULL; + struct DIR_ACL *dir_acl = NULL; + struct stat stat_buf; + struct stringbuf *filename = NULL; + char buf[MAX_LINE_SIZE]; + + errno = 0; + + if (stat(dir, &stat_buf) == -1) + goto err; + + dir_acl = create_dir_acl(dir); + if (!dir_acl) + goto err; + filename = dup_stringbuf(dir_acl->dirname); - if (filename == NULL) { - free(dir_acl); - return NULL; - } - cat_stringbuf(filename, "/DIRACL"); + if (!filename) + goto err; + if (!cat_stringbuf(filename, "/DIRACL")) + goto err; + /* DIRACL file could be missing */ acl = fopen(filename->buf, "r"); - if (acl == NULL) - goto out; + if (acl == NULL) { + if (errno == ENOENT) + goto out; + else + goto err; + } while (fgets(buf, MAX_LINE_SIZE, acl) != NULL) { int len = strlen(buf); @@ -261,11 +318,17 @@ char *username; char *perm_string; - if (buf[len - 1] != '\n') + /* too long line */ + if (buf[len - 1] != '\n') { + errno = E2BIG; goto err; + } buf[len - 1] = '\0'; initial_char = *p++; + /* ignore unknown initial line types */ + /* FIXME: those lines are not preserved when older server + rewrites DIRACL file */ if ((initial_char != '/') && (initial_char != 'D')) continue; @@ -273,7 +336,7 @@ while (*p && (*p != '\t')) p++; if (!*p) - goto err; + goto inval; *p++ = '\0'; username = p; @@ -281,7 +344,7 @@ while (*p && (*p != '\t')) p++; if (!*p) - goto err; + goto inval; *p++ = '\0'; perm_string = p; @@ -290,7 +353,7 @@ p++; if (*p) - goto err; + goto inval; if (initial_char == '/') set_dir_ace(dir_acl, username, parse_dir_permissions(perm_string)); @@ -298,16 +361,19 @@ set_default_file_acl(dir_acl, branch, username, parse_branch_permissions(perm_string)); } - fclose(acl); - out: - return dir_acl; - - err: free_stringbuf(filename); if (acl != NULL) fclose(acl); - return NULL; + return dir_acl; + + inval: + errno = EINVAL; + + err: + destroy_dir_acl(dir_acl); + dir_acl = NULL; + goto out; } @@ -535,6 +601,7 @@ cat_stringbuf(line, dir_permissions_string(user_acl->perm)); catc_stringbuf(line, '\n'); + /* FIXME: change to fprintf() */ if (write(fd, line->buf, line->len) != line->len) goto out; |