[Cvs-nserver-commits] CVS: cvs-nserver/src lsacl.c,1.1.2.5,1.1.2.6
Brought to you by:
tyranny
From: Alexey M. <mo...@us...> - 2002-06-20 17:12:29
|
Update of /cvsroot/cvs-nserver/cvs-nserver/src In directory usw-pr-cvs1:/tmp/cvs-serv8102 Modified Files: Tag: NCLI-1-11-1 lsacl.c Log Message: lsacl now gives output that can be parsed w/ AI :-) Index: lsacl.c =================================================================== RCS file: /cvsroot/cvs-nserver/cvs-nserver/src/Attic/lsacl.c,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -d -r1.1.2.5 -r1.1.2.6 --- lsacl.c 23 Mar 2002 15:30:23 -0000 1.1.2.5 +++ lsacl.c 20 Jun 2002 17:12:22 -0000 1.1.2.6 @@ -21,216 +21,176 @@ #include "acl.h" #include "lsacl.h" #include "recurse.h" +#include "default-file-acl.h" +#include "stringbuf.h" #include <stdlib.h> static int local_only = 1; -static int deep = 0; -static size_t skip_prefix = 0; -static char *tagname = NULL; - +static int with_contents = 0; +static const char *branch = "trunk"; +static int error_counter = 0; +static int parent_list = 1; +static int all_branches = 0; +static struct stringbuf *outputbuf = NULL; static const char *const lsacl_usage[] = { - "Usage: %s %s subdirectories...\n", - "\t-R\tRecursively list ACLs.\n", + "Usage: %s %s [-l | -R] [-r rev] [-c] modules...\n", + "\t-l\tLocal directory only, not recursive\n", + "\t-R\tProcess directories recursively.\n", + "\t-r rev\tList Branch ACLs for the specified branch.\n", + "\t-c\tInclude listing of ACL for directory contents.\n", NULL }; -static struct stringbuf * -get_fulldir (char* relative_name) -{ - struct stringbuf *fulldir = new_stringbuf(current_parsed_root->directory); - if (!fulldir) - return NULL; - - catc_stringbuf(fulldir, '/'); - cat_stringbuf(fulldir, relative_name); - - return fulldir; -} +#define THIS_DIR_PREFIX "D/" +#define THIS_FILE_PREFIX "/" +#define THIS_ACL_PREFIX "\tD/" +#define PARENT_ACL_PREFIX "\tD/" +#define DEFAULT_FILE_ACL_PREFIX "\tDB/" +#define BRANCH_ACL_PREFIX "\tB/" +#define FIELD_SEPARATOR "//" +#define RECORD_SEPARATOR "\n" +#ifndef PATH_SEPARATOR +# define PATH_SEPARATOR "/" +#endif -static void -forbidden_in (struct stringbuf* line, char* what, struct stringbuf* dirname) -{ - int saved_len = line->len; - cat_stringbuf(line, what); - cat_stringbuf(line, " forbidden in "); - cat_stringbuf(line, dirname->buf); - catc_stringbuf(line, '\n'); - cvs_output(line->buf, line->len); - shrink_stringbuf(line, saved_len); -} +typedef const char* (*FORMACLFUNC)(int); -static void -forbidden (struct stringbuf* line, char* what) -{ - int saved_len = line->len; - cat_stringbuf(line, what); - cat_stringbuf(line, " forbidden\n"); - cvs_output(line->buf, line->len); - shrink_stringbuf(line, saved_len); +/* + FIXME: this procedure is UNIX file name convention oriented. + Probably porting to other systems will require significant rewriting + :-/ +*/ +static char *get_canon_dir(const char *const repos, const char *const dir) { + char *result = NULL; + char *dirp; + int i,j; + if (dir==NULL || repos == NULL) + return NULL; + dirp = xstrdup(repos + strlen(current_parsed_root->directory)); + if (dirp == NULL) + return NULL; + for(i=0;dirp[i]=='/';i++); + for(j = strlen(dirp) - 1; j >= i && dirp[j] == '/'; j--); + if (i > j) { + result = xstrdup("."); + goto err; + } + + if ((result = malloc(j-i+2))==NULL) + goto err; + strncpy(result, dirp + i, j-i + 1); + result[j-i+1] = '\0'; + err: + free(dirp); + return result; } -enum topdirs_what { TOPDIRS_DIRECTORY, TOPDIRS_FILE }; -static void -print_out_topdir_acls (DIR_ACL** topdir_acls, enum topdirs_what what, char* filename, struct stringbuf* line) +static int +print_user_acls(const USER_ACL *user_acl, FORMACLFUNC form_acl_string, + const char *const prefix, + const char *const fname, const char *const branch) { - if (topdir_acls) { - for (; *topdir_acls; topdir_acls++) { - DIR_ACL* topdir_acl = *topdir_acls; - USER_ACL* user_acl = topdir_acl->user_acls; - - while (user_acl) { - int saved_len = line->len; - if (filename) { - cat_stringbuf(line, filename); - catc_stringbuf(line, '/'); - } - - cat_stringbuf(line, user_acl->username); - catc_stringbuf(line, '/'); - cat_stringbuf(line, "parent/"); - switch (what) { - case TOPDIRS_DIRECTORY: - if ((user_acl->perm & dir_perm_access) != dir_perm_access) - forbidden_in(line, "access", topdir_acl->dirname); - - if ((user_acl->perm & dir_perm_modify) != dir_perm_modify) - forbidden_in(line, "modify", topdir_acl->dirname); - break; - - case TOPDIRS_FILE: - if ((user_acl->perm & branch_perm_checkin) != branch_perm_checkin) - forbidden_in(line, "checkin", topdir_acl->dirname); - - if ((user_acl->perm & branch_perm_checkout) != branch_perm_checkout) - forbidden_in(line, "checkout", topdir_acl->dirname); - - break; - } - - shrink_stringbuf(line, saved_len); - user_acl = user_acl->next; - } + stringbuf *ptr = outputbuf; + int is_ok = 1; + for(;user_acl; user_acl = user_acl->next) { + ptr = cat_stringbuf(ptr, prefix); + ptr = cat_stringbuf(ptr, user_acl->username); + ptr = cat_stringbuf(ptr,FIELD_SEPARATOR); + ptr = cat_stringbuf(ptr, form_acl_string(user_acl->perm)); + ptr = cat_stringbuf(ptr, FIELD_SEPARATOR); + if (branch != NULL) { + ptr = cat_stringbuf(ptr, branch); + ptr = cat_stringbuf(ptr, FIELD_SEPARATOR); + } + ptr = cat_stringbuf(ptr,fname); + ptr = cat_stringbuf(ptr,RECORD_SEPARATOR); + if (ptr == NULL) { + shrink_stringbuf(outputbuf,0); + is_ok = 0; + //break; + } else { + cvs_output(outputbuf->buf,0); + shrink_stringbuf(outputbuf,0); } } + return is_ok; } static int -print_out_acls_for_file(char* relative_name, char* filename, char* dirname, char* branch) +print_default_branch_acls (const struct DEFAULT_FILE_ACL *acl, + FORMACLFUNC form_acl_string, + const char * const prefix) { - int retval = 0; - char* xbranch = branch ? branch : "trunk"; - struct stringbuf* line = NULL; - struct stringbuf* fullname = NULL; - struct DIR_ACL* diracl; - struct BRANCH_ACL* branch_acl; - struct BRANCH_ACE* file_ace; - - diracl = get_dir_acl(dirname, xbranch); - if (!diracl) - error(errno, 0, "Error getting directory ACLs for %s\n", dirname); - - line = new_stringbuf("/"); - if (!line) - goto err; - - cat_stringbuf(line, filename); - catc_stringbuf(line, '/'); - - print_out_topdir_acls(diracl->top_dirs, TOPDIRS_FILE, NULL, line); - - branch_acl = get_branch_acl(diracl, xbranch); - file_ace = get_file_on_branch_ace(branch_acl, filename); - if (file_ace) { - struct USER_ACL* user_acl = file_ace->user_acls; - while (user_acl) { - int saved_len = line->len; - - cat_stringbuf(line, user_acl->username); - cat_stringbuf(line, "/here/"); - - if ((user_acl->perm & branch_perm_checkin) != branch_perm_checkin) - forbidden(line, "checkin"); - - if ((user_acl->perm & branch_perm_checkout) != branch_perm_checkout) - forbidden(line, "checkout"); - - shrink_stringbuf(line, saved_len); - - user_acl = user_acl->next; + stringbuf *ptr = outputbuf; + int is_ok = 1; + for(;acl; acl = acl->next) { + USER_ACL *user_acl = acl->user_acl; + if (strcmp(acl->branch, branch) != 0) + continue; + for(;user_acl; user_acl = user_acl->next) { + ptr = cat_stringbuf(ptr, prefix); + ptr = cat_stringbuf(ptr, user_acl->username); + ptr = cat_stringbuf(ptr,FIELD_SEPARATOR); + ptr = cat_stringbuf(ptr, form_acl_string(user_acl->perm)); + ptr = cat_stringbuf(ptr, FIELD_SEPARATOR); + ptr = cat_stringbuf(ptr, acl->branch); + ptr = cat_stringbuf(ptr, RECORD_SEPARATOR); + if (ptr == NULL) { + shrink_stringbuf(outputbuf, 0); + is_ok = 0; + //goto out; + } else { + cvs_output(outputbuf->buf,0); + shrink_stringbuf(outputbuf,0); + } } } - - retval = 1; - err: - free_stringbuf(line); - return retval; + out: + return is_ok; } static int -print_out_acls_for_dir(char* relative_name, char* branch) +plain_lsacl_dirproc (const char *dir, const DIR_ACL *dir_acl) { - int retval = 0; - int saved_len; - struct stringbuf* fulldir = NULL; - struct stringbuf* line = NULL; - DIR_ACL* dir_acl = NULL; - USER_ACL* user_acl; - - fulldir = get_fulldir(relative_name); - if (!fulldir) - goto out; - - line = new_stringbuf("DP/"); - if (!line) - goto out; - saved_len = line->len; - - if (fulldir->buf[fulldir->len - 1] == '/') - fulldir->buf[fulldir->len - 1] = '\0'; - - dir_acl = get_dir_acl(fulldir->buf, branch); - if (!dir_acl) - goto out; - - /* print out permissions denied in one of the top directories */ - print_out_topdir_acls(dir_acl->top_dirs, TOPDIRS_DIRECTORY, NULL, line); - - /* print out permissions denied in this directory */ - user_acl = dir_acl->user_acls; - while (user_acl) { - int saved_len = line->len; - cat_stringbuf(line, user_acl->username); - cat_stringbuf(line, "/here/"); - if ((user_acl->perm & dir_perm_access) != dir_perm_access) - forbidden(line, "access"); - - if ((user_acl->perm & dir_perm_modify) != dir_perm_modify) - forbidden(line, "modify"); + size_t rootlen = strlen(current_parsed_root->directory); + struct stringbuf *ptr = outputbuf; - shrink_stringbuf(line, saved_len); - user_acl = user_acl->next; + ptr = cat_stringbuf(ptr, THIS_DIR_PREFIX); + ptr = cat_stringbuf(ptr, dir); + ptr = cat_stringbuf(ptr, RECORD_SEPARATOR); + if (ptr == NULL) { + error(0,0,"Out of memory"); + shrink_stringbuf(outputbuf,0); + return 0; } + cvs_output(outputbuf->buf,0); + shrink_stringbuf(outputbuf,0); - retval = 1; - out: - free_stringbuf(fulldir); - free_stringbuf(line); - return retval; -} - - -static int -lsacl_fileproc (void *callerdat, struct file_info *finfo) -{ - print_out_acls_for_file(finfo->fullname, finfo->file, finfo->repository, tagname); - - return 0; + if (parent_list && dir_acl->top_dirs) { + DIR_ACL **topdir; + for(topdir = dir_acl->top_dirs; *topdir; topdir++) { + char *pdir = get_canon_dir((*topdir)->dirname->buf, (*topdir)->dirname->buf + rootlen); + if (pdir == NULL) { + error(0,0,"Out of memory"); + return 0; + } + print_user_acls((*topdir)->user_acls, dir_permissions_string, + PARENT_ACL_PREFIX, pdir, NULL); + free(pdir); + } + } + print_user_acls(dir_acl->user_acls, dir_permissions_string, + THIS_ACL_PREFIX,"",NULL); + print_default_branch_acls(dir_acl->default_file_acl, + branch_permissions_string, + DEFAULT_FILE_ACL_PREFIX); + return 1; } /* ARGSUSED */ @@ -242,37 +202,128 @@ char *update_dir; List *entries; { - /* Should we go this way? AM */ + DIR_ACL *dir_acl = NULL; + char *canon_dir = NULL; + dir_permission dir_perm = dir_perm_all; + int is_error = 0; + + if ((canon_dir = get_canon_dir(repository, update_dir))==NULL) { + error(0, 0, "Out of memory"); + error_counter++; + return R_SKIP_ALL; + } #ifdef SERVER_SUPPORT - int grant = grant_dir_permission(repository, dir, dir_perm_access, "list"); -#else - int grant = 1; + if ((dir_acl = get_dir_acl(repository,branch)) == NULL) { + error(0, errno, "Error getting directory ACL for '%s'", canon_dir); + is_error = 1; + goto err; + } + dir_perm = dir_permission_granted(dir_acl,CVS_Username,dir_perm_access); + if (!(dir_perm & dir_perm_access)) { + error(0,0,"ACL list permission denied for %s in '%s'", + CVS_Username, canon_dir); + is_error = 1; + goto err; + } #endif - if (deep > 0) { - cvs_output("D", 1); + is_error = !plain_lsacl_dirproc(canon_dir, dir_acl); + err: + destroy_dir_acl(dir_acl); + free(canon_dir); + if (is_error) { + error_counter++; + return R_SKIP_ALL; + } else { + return ((with_contents) ? R_PROCESS : R_SKIP_ALL); + } +} - if (!skip_prefix) - cvs_output("/",1); - - /* Is it really safe. I mean is 'update_dir' is always - * startdir + smth? - */ - cvs_output(update_dir + skip_prefix, 0); - if (!grant) - cvs_output("//locked",0); - cvs_output("\n", 1); +static int +plain_lsacl_fileproc(const char *const dir, struct file_info *finfo, + struct BRANCH_ACE *ace) +{ + size_t rootlen = strlen(current_parsed_root->directory); + struct stringbuf *ptr = outputbuf; + + ptr = cat_stringbuf(ptr, THIS_FILE_PREFIX); + ptr = cat_stringbuf(ptr, dir); + ptr = cat_stringbuf(ptr, PATH_SEPARATOR); + ptr = cat_stringbuf(ptr, finfo->file); + ptr = cat_stringbuf(ptr, RECORD_SEPARATOR); + if (ptr == NULL) { + error(0,0,"Out of memory"); + shrink_stringbuf(outputbuf,0); + return 0; } - deep++; - print_out_acls_for_dir(update_dir, tagname); + cvs_output(outputbuf->buf,0); + shrink_stringbuf(outputbuf,0); -#ifdef SERVER_SUPPORT - if (!grant) - return R_SKIP_ALL; -#endif - if (local_only && deep > 1) - return R_SKIP_ALL; - return R_PROCESS; + /* Print inherited ACLs */ + if (parent_list && ace->acl && ace->acl->dir_acl) { + if (ace->acl->dir_acl->top_dirs) { + DIR_ACL **topdir; + for(topdir = ace->acl->dir_acl->top_dirs; *topdir; topdir++) { + char *pdir = get_canon_dir((*topdir)->dirname->buf, (*topdir)->dirname->buf + rootlen); + if (pdir == NULL) { + error(0,0,"Out of memory"); + return 0; + } + print_user_acls((*topdir)->user_acls, dir_permissions_string, + PARENT_ACL_PREFIX, pdir, NULL); + free(pdir); + } + } + print_user_acls(ace->acl->dir_acl->user_acls, dir_permissions_string, + PARENT_ACL_PREFIX,dir,NULL); + print_default_branch_acls(ace->acl->dir_acl->default_file_acl, + branch_permissions_string, + DEFAULT_FILE_ACL_PREFIX); + } + print_user_acls(ace->user_acls, branch_permissions_string, + BRANCH_ACL_PREFIX,"",branch); + return 1; +} + +static int +lsacl_fileproc (void *callerdat, struct file_info *finfo) +{ + DIR_ACL *dir_acl = NULL; + BRANCH_ACL *branch_acl = NULL; + BRANCH_ACE *branch_ace = NULL; + char *canon_dir = NULL; + int is_error = 0; + + if ((canon_dir=get_canon_dir(finfo->repository,finfo->update_dir))==NULL) { + error(0, errno, "Out of memory"); + is_error = 1; + goto err; + } + if ((dir_acl = get_dir_acl(finfo->repository,branch)) == NULL) { + error(0, errno, + "Error getting directory ACL for '%s'", canon_dir); + is_error = 1; + goto err; + } + if ((branch_acl = get_branch_acl(dir_acl,branch))==NULL) { + error(0, errno, + "Error getting branch ACL for '%s'", canon_dir); + is_error = 1; + goto err; + } + if ((branch_ace = get_file_on_branch_ace(branch_acl,finfo->file))==NULL) { + error(0, errno, + "Error getting file ACE for '%s/%s'", canon_dir,finfo->file); + is_error = 1; + goto err; + } + is_error = !plain_lsacl_fileproc(canon_dir, finfo, branch_ace); + err: + free(canon_dir); + /* Place destroy_branch_acl and destroy_branch_ace when + appropriate function will be ready */ + destroy_dir_acl(dir_acl); + return ((is_error) ? 1 : 0); } static int @@ -280,31 +331,91 @@ char *mwhere, char *mfile, int shorten, int local, char *mname, char *msg) { + char *myargv[2]; int err = 0; int which = W_REPOS | W_ATTIC; - struct stringbuf* repository; + + struct stringbuf *repository = NULL; + struct stringbuf *rptr = NULL; - skip_prefix = (strcmp(".",argv[1])) ? strlen(argv[1]) : 0; + struct stringbuf *where; + struct stringbuf *wptr; + outputbuf = NULL; repository = new_stringbuf(current_parsed_root->directory); + rptr = catc_stringbuf(repository, '/'); + rptr = cat_stringbuf(rptr, argv[0]); + + where = new_stringbuf(argv[0]); + wptr = where; - if (CVS_CHDIR(repository->buf) < 0) { + if (rptr == NULL || wptr == NULL) { + error(0, 0, "Not enough memory for repository stringbuf"); err = 1; - goto out; + goto err; } + + + /* if mfile isn't null, we need to set up to do only part of the module */ + if (mfile != NULL) + { + + rptr = catc_stringbuf(rptr, '/'); + rptr = cat_stringbuf(rptr,mfile); + wptr = catc_stringbuf(wptr, '/'); + wptr = cat_stringbuf(wptr, mfile); + if (rptr == NULL || wptr == NULL) { + error(0, errno, "Not enough memory for repository stringbuf"); + err = 1; + goto err; + } - deep = 0; - local = 0; /* we always use recursion mode, 'cause we anyway need - subdirectores listing - */ - err = start_recursion (lsacl_fileproc, (FILESDONEPROC) NULL, lsacl_dirproc, - (DIRLEAVEPROC) NULL, (void *) NULL, - argc - 1, argv + 1, local, which, 0, 1, - "", 1); + if (!isdir(repository->buf)) { + /* Hmm... It's a file. we have to cut off its + * basename from repository... */ + size_t mflen; + char *sp = strrchr(mfile, '/'); + if (sp != NULL) + mfile = sp + 1; + mflen = strlen(mfile); + repository->buf[repository->len - mflen - 1] = '\0'; + repository->len -= (mflen + 1); + where->buf[where->len - mflen - 1] = '\0'; + where->len -= (mflen + 1); - out: - free_stringbuf(repository); - return err; + /* copied from patch.c w/o checking if this really way to + go :-) */ + myargv[0] = argv[0]; + myargv[1] = mfile; + argc = 2; + argv = myargv; + } + } + + /* cd to the starting repository */ + if ( CVS_CHDIR (repository->buf) < 0) { + error(0, errno, "Error changing working directory to %s", + repository->buf); + err = 1; + goto err; + } + outputbuf = new_stringbuf(""); + if (outputbuf == NULL) { + error(0, errno, "Not enough memory for output stringbuf"); + err = 1; + goto err; + } + + /* start the recursion processor */ + err = start_recursion (lsacl_fileproc,(FILESDONEPROC) NULL, + lsacl_dirproc, (DIRLEAVEPROC) NULL, + (void*)msg, argc - 1, argv + 1, local_only, + which, 0, 1, where->buf, 1); + err: + free_stringbuf(where); where = NULL; + free_stringbuf(repository); repository = NULL; + free_stringbuf(outputbuf); outputbuf = NULL; + return (err); } @@ -313,33 +424,31 @@ { int err = 0; int i; - - for (i = 0; i < argc; i++) { - err += lsacl_proc (argc + 1, argv - 1, (char *) NULL, - (char *) NULL, (char *) NULL, 0, local_only, (char *) NULL, - (char *) NULL); - } - return err; -} - -int -lsacl (int argc, char** argv) -{ int c; + DBM *db; + + argv++; /* skip 'cvs server' */ + /* argv++; */ /* Due to the bug of getopt(3) we don't need to + skip 'racl' */ + argc--; optind = 0; - while ((c = getopt (argc, argv, "Rr:")) != -1) + while ((c = getopt (argc, argv, "clRr:")) != -1) { switch (c) { case 'R': local_only = 0; break; - + case 'l': + local_only = 1; + break; + case 'c': + with_contents = 1; + break; case 'r': - tagname = xstrdup(optarg); + branch = xstrdup(optarg); break; - default: usage(lsacl_usage); break; @@ -349,32 +458,55 @@ argc -= optind; argv += optind; + if (argc < 1 || !(*argv[0])) usage (lsacl_usage); - -#ifdef CLIENT_SUPPORT - if (current_parsed_root->isremote) { - int i; + error_counter = 0; + db = open_module (); + for (i = 0; i < argc; i++) + err += do_module (db, argv[i], MISC, (char *) NULL, lsacl_proc, + (char *) NULL, 0, local_only, 0, 0, (char*) NULL); + close_module (db); + return err + error_counter; +} - start_server(); +#ifdef CLIENT_SUPPORT +static int client_side_lsacl(int argc, char **argv) { + int i; + start_server(); - ign_setup(); + ign_setup(); - if (!local_only) - send_to_server ("Argument -R\012", 0); + if (!supported_request ("lsacl")) + error (1, 0, "server does not support lsacl"); - if (tagname != NULL) - option_with_arg ("-r", tagname); + for (i = 0; i < argc; i++) { + send_arg(argv[i]); + } - for (i = 0; i < argc; i++) - send_arg (argv[i]); + send_to_server ("lsacl\012", 0); - send_to_server("lsacl\012", 0); + return get_responses_and_close(); +} +#endif - return get_responses_and_close(); - } -#endif /* CLIENT_SUPPORT */ +int +lsacl (int argc, char** argv) +{ + if (argc == -1) + usage(lsacl_usage); + +#ifdef SERVER_SUPPORT + if (server_active) + return server_side_lsacl(argc, argv); +#endif - return server_side_lsacl(argc, argv); +#ifdef CLIENT_SUPPORT + if (current_parsed_root->isremote) + return client_side_lsacl(argc, argv); +#endif + return 0; } + + |