Module Name: src
Committed By: christos
Date: Thu Mar 8 20:32:31 UTC 2012
Added Files:
src/external/gpl2/xcvs/dist/src: acl.c
Log Message:
acl support
To generate a diff of this commit:
cvs rdiff -u -r0 -r1.1 src/external/gpl2/xcvs/dist/src/acl.c
Please note that diffs are not public domain; they are subject to the
copyright notices on the relevant files.
Added files:
Index: src/external/gpl2/xcvs/dist/src/acl.c
diff -u /dev/null src/external/gpl2/xcvs/dist/src/acl.c:1.1
--- /dev/null Thu Mar 8 15:32:31 2012
+++ src/external/gpl2/xcvs/dist/src/acl.c Thu Mar 8 15:32:31 2012
@@ -0,0 +1,2162 @@
+/*
+ * Copyright (C) 2006 The Free Software Foundation, Inc.
+ *
+ * Portions Copyright (C) 2006, Baris Sahin <sbaris at users.sourceforge.net>
+ * <http://cvsacl.sourceforge.net>
+ *
+ *
+ * You may distribute under the terms of the GNU General Public License as
+ * specified in the README file that comes with the CVS source distribution.
+ *
+ *
+ *
+ * CVS ACCESS CONTROL LIST EXTENSION
+ *
+ * It provides advanced access control definitions per modules,
+ * directories, and files on branch/tag for remote cvs repository
+ * connections.Execution of all CVS subcommands can be controlled
+ * with eight different permissions.
+ *
+ * Permission Types:
+ * - no permission (n) (1)
+ * - all permissions (a) (2)
+ * - write permission (w) (3)
+ * - tag permission (t) (4)
+ * - read permission (r) (5)
+ * - add permission (c) (6)
+ * - remove permission (d) (7)
+ * - permission change (p) (8)
+ *
+ */
+#include "cvs.h"
+#include "getline.h"
+#include <grp.h>
+
+#define free(x) (void)(x)
+
+static int acl_fileproc (void *callerdat, struct file_info *finfo);
+
+static Dtype acl_dirproc (void *callerdat, const char *dir, const char *repos,
+ const char *update_dir, List *entries);
+
+static int acllist_fileproc (void *callerdat, struct file_info *finfo);
+static Dtype acllist_dirproc (void *callerdat, const char *dir,
+ const char *repos, const char *update_dir,
+ List *entries);
+
+static void acllist_print (char *line, const char *obj);
+
+static int racl_proc (int argc, char **argv, char *xwhere,
+ char *mwhere, char *mfile, int shorten,
+ int local_specified, char *mname, char *msg);
+
+static FILE *open_accessfile (char *xmode, const char *repos, char **fname);
+static FILE *open_groupfile (char *xmode);
+
+static char *get_perms (const char *xperms);
+static char *make_perms (char *xperms, char *xfounduserpart, char **xerrmsg);
+
+static char *findusername (const char *string1, const char *string2);
+static char *findgroupname (const char *string1, const char *string2);
+static int valid_tag (const char *part_tag, const char *tag);
+static int valid_perm (const char *part_perms, int perm);
+static int write_perms (const char *user, const char *perms,
+ const char *founduserpart, int foundline,
+ char *otheruserparts, const char *part_type,
+ const char *part_object, const char *part_tag, int pos,
+ const char *arepos);
+
+static char *cache_repository;
+static int cache_retval;
+static int founddeniedfile;
+static int cache_perm;
+
+static int is_racl;
+static int debug = 0;
+
+int use_cvs_acl = 0;
+char *cvs_acl_default_permissions;
+int use_cvs_groups = 0;
+int use_system_groups = 0;
+int use_separate_acl_file_for_each_dir = 0;
+char *cvs_acl_file_location = NULL;
+char *cvs_groups_file_location = NULL;
+char *cvs_server_run_as = NULL;
+int stop_at_first_permission_denied = 0;
+
+char *tag = NULL;
+
+char *muser;
+char *mperms;
+static int defaultperms;
+
+static char *default_perms_object;
+char *default_part_perms_accessfile;
+int aclconfig_default_used;
+
+int acldir = 0;
+int aclfile = 0;
+int listacl = 0;
+
+int userfound = 0;
+int groupfound = 0;
+
+/* directory depth ... */
+char *dirs[255];
+
+static const char *const acl_usage[] =
+ {
+ "Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...] [files...]\n",
+ "\t-R\tProcess directories recursively.\n",
+ "\t-r rev\tExisting revision/tag.\n",
+ "\t-l\tList defined ACLs.\n",
+ "(Specify the --help global option for a list of other help options)\n",
+ NULL
+ };
+
+static const char *const racl_usage[] =
+{
+ "Usage: %s %s [user||group:permissions] [-Rl] [-r tag] [directories...]"
+ " [files...]\n",
+ "\t-R\tProcess directories recursively.\n",
+ "\t-r rev\tExisting revision/tag.\n",
+ "\t-l\tList defined ACLs.\n",
+ "(Specify the --help global option for a list of other help options)\n",
+ NULL
+};
+
+
+int
+access_allowed (const char *file, const char *repos, const char *tag,
+ int perm, char **mline, int *mpos, int usecache)
+{
+ int retval = 0;
+ int foundline = 0;
+ FILE *accessfp;
+
+ int flag = 1;
+
+ char *iline;
+ char *tempv;
+ char *tempc;
+ size_t tempsize;
+
+ int intcount;
+ int accessfilecount;
+ int signlevel = -1;
+ int dadmin = 0;
+
+ const char *repository;
+ char *filefullname = NULL;
+ userfound = 0;
+ groupfound = 0;
+
+ if (defaultperms)
+ {
+ repository = xstrdup ("ALL");
+ }
+ else {
+ if (strlen(repository = Short_Repository (repos)) == 0)
+ {
+ repository = xstrdup (".");
+ }
+ }
+
+ /* cache */
+ if (usecache && cache_repository != NULL &&
+ strcmp (cache_repository, repository) == 0 && !founddeniedfile
+ && perm == cache_perm)
+ return (cache_retval);
+ else
+ {
+ free (cache_repository);
+ cache_repository = xstrdup (repository);
+ cache_perm = perm;
+ }
+
+ iline = xstrdup(repository);
+
+ tempv = strtok(iline, "/\t");
+ tempc = xstrdup(tempv);
+ tempsize = ( tempc != NULL ) ? strlen(tempc) : 0;
+
+ intcount = 0;
+ /* store paths from object to cvsroot */
+ dirs[intcount] = xstrdup(tempc);
+ while ((tempv = strtok(NULL, "/\t")) != NULL)
+ {
+ intcount++;
+
+ xrealloc_and_strcat(&tempc, &tempsize, "/");
+ xrealloc_and_strcat(&tempc, &tempsize, tempv);
+
+ dirs[intcount] = xstrdup(tempc);
+ }
+
+ /* free not needed variables here */
+ free (tempv);
+ free (tempc);
+ free (iline);
+
+ /* accessfilecount will used
+ * if UseSeparateACLFile keyword is set to yes*/
+ accessfilecount = intcount;
+
+ /* if file is not null add it to dirs array */
+ if (file != NULL)
+ {
+ filefullname = Xasprintf("%s/%s", repository, file);
+ intcount++;
+ dirs[intcount] = xstrdup(filefullname);
+ }
+
+ for (accessfilecount; accessfilecount >= 0 && flag; accessfilecount--)
+ {
+ if (!use_separate_acl_file_for_each_dir) {
+ flag = 0;
+ accessfp = open_accessfile ("r", repository, NULL);
+ }
+ else
+ {
+ flag = 1;
+ accessfp = open_accessfile ("r", dirs[accessfilecount], NULL);
+ }
+
+ if (accessfp != NULL)
+ {
+ char *line = NULL;
+ size_t line_allocated = 0;
+
+ char *xline;
+ char *part_type = NULL;
+ char *part_object = NULL;
+ char *part_tag = NULL;
+ char *part_perms = NULL;
+
+ int x;
+
+ while (getline (&line, &line_allocated, accessfp) >= 0)
+ {
+
+ if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
+ continue;
+
+ xline = xstrdup (line);
+ part_type = strtok (line, ":\t");
+ part_object = strtok (NULL, ":\t");
+ part_tag = strtok (NULL, ":\t");
+ part_perms = strtok (NULL, ":\t");
+
+ if (part_type == NULL || part_object == NULL ||
+ part_tag == NULL || part_perms == NULL)
+ {
+ free (line);
+ error(1, 0, "access file is corrupted or has invalid"
+ " format");
+ }
+
+ if (debug) fprintf (stderr, "type %s object %s tag %s perms"
+ "%s\n", part_type, part_object, part_tag,
+ part_perms);
+ for (x = intcount; x >= signlevel && x != -1; x--)
+ {
+ if (debug) fprintf (stderr, "dirs[%d] = %s, part_object="
+ "%s\n", x, dirs[x], part_object);
+ if (strcmp (dirs[x], part_object) == 0)
+ {
+ if (debug) fprintf(stderr, "tag %s \n", tag);
+ if (valid_tag (part_tag, tag))
+ {
+ foundline = 1;
+ if (debug) fprintf(stderr, "foundline\n");
+
+ if (listacl || ((acldir || aclfile) &&
+ x == intcount) &&
+ strcmp(part_tag, tag) == 0)
+ {
+ *mline = xstrdup (xline);
+ *mpos = ftell (accessfp);
+ }
+
+ if (debug) fprintf(stderr, "perm %d\n", perm);
+ if (valid_perm (part_perms, perm))
+ {
+ if (signlevel == x)
+ {
+ if (strcmp(part_tag, "ALL") != 0 &&
+ !aclconfig_default_used)
+ retval = 1;
+ }
+ else if (!aclconfig_default_used)
+ {
+ signlevel = x;
+ retval = 1;
+ }
+ else {
+ /* nothing... */
+ }
+ }
+ else
+ {
+ if (signlevel == x)
+ {
+ if (strcmp(part_tag, "ALL") != 0 &&
+ !aclconfig_default_used)
+ retval = 0;
+ }
+ else if (!aclconfig_default_used)
+ {
+ signlevel = x;
+ retval = 0;
+
+ if (strncmp (part_type, "f", 1) == 0)
+ founddeniedfile = 1;
+ }
+ else {
+ }
+ }
+ }
+ }
+ }
+
+ if (debug) fprintf (stderr, "xline tag = %s %d %d\n", xline,
+ groupfound, userfound);
+ if (strncmp (xline, "d:ALL:", 6) == 0 &&
+ ((!groupfound && !userfound) || listacl))
+ {
+ if (debug) fprintf (stderr, "ALL tag = %s\n", tag);
+ /* a default found */
+ if (valid_tag (part_tag, tag) > 0)
+ {
+ foundline = 1;
+
+ default_part_perms_accessfile = xstrdup (part_perms);
+
+ if (debug) fprintf (stderr, "valid perm = %d\n", perm);
+ if (valid_perm (part_perms, perm))
+ {
+ retval = 1;
+ if (perm == 8)
+ dadmin = 1;
+ }
+ else
+ retval = 0;
+ }
+ }
+
+ }
+
+ if (fclose (accessfp) == EOF)
+ error (1, errno, "cannot close 'access' file");
+ }
+ }
+
+ if (!foundline)
+ {
+ if (debug) fprintf(stderr, "not found line\n");
+ /* DEFAULT */
+ if (valid_perm (NULL, perm))
+ retval = 1;
+ else
+ retval = 0;
+ }
+
+ /* acl admin rigths 'p' */
+ if (dadmin)
+ {
+ retval = dadmin;
+ }
+
+ cache_retval = retval;
+
+ free (filefullname);
+ /* free directories array */
+ while (intcount >= 0)
+ {
+ free (dirs[intcount]);
+ intcount--;
+ }
+
+ return retval;
+}
+
+/* Returns 1 if tag is valid, 0 if not */
+static int
+valid_tag (const char *part_tag, const char *tag)
+{
+ int retval;
+
+ if (tag == NULL)
+ tag = "HEAD";
+
+ if (strcmp (tag, part_tag) == 0 || strcmp (part_tag, "ALL") == 0)
+ retval = 1;
+ else
+ retval = 0;
+
+ return retval;
+}
+
+/* Returns 1 if successful, 0 if not. */
+static int
+valid_perm (const char *part_perms, int perm)
+{
+ char *perms;
+ int retval = 0;
+
+ perms = get_perms (part_perms);
+
+ /* Allow, if nothing found. */
+ if (perms[0] == '\0')
+ return (1);
+
+ /* no access allowed, exit */
+ if (strstr (perms, "n"))
+ retval = 0;
+
+ if (strstr (perms, "p"))
+ /* admin rights */
+ retval = 1;
+ else if (strstr (perms, "a") && perm != 8)
+ /* all access allowed, exit */
+ retval = 1;
+ else
+ switch (perm)
+ {
+ case 3:/* write permission */
+ if (strstr (perms, "w"))
+ retval = 1;
+ break;
+ case 4:/* tag permission */
+ if (strstr (perms, "t"))
+ retval = 1;
+ break;
+ case 5:/* read permission */
+ if (strstr (perms, "w") || strstr (perms, "t") ||
+ strstr (perms, "c") || strstr (perms, "d") ||
+ strstr (perms, "r"))
+ retval = 1;
+ break;
+ case 6:/* create permission */
+ if (strstr (perms, "c"))
+ retval = 1;
+ break;
+ case 7:/* delete permission */
+ if (strstr (perms, "d"))
+ retval = 1;
+ break;
+ case 8:/* permission change */
+ if (strstr (perms, "p"))
+ retval = 1;
+ break;
+ default:/* never reached */
+ retval = 0;
+ break;
+ }
+
+ free (perms);
+
+ return (retval);
+}
+
+/* returns permissions found */
+char *
+get_perms (const char *part_perms)
+{
+ char *username;
+ char *xperms;
+ size_t xperms_len = 1;
+
+ FILE *groupfp;
+
+ char *founduser = NULL;
+ char *foundall = NULL;
+ int default_checked = 0;
+
+ if (debug) fprintf (stderr, "get_perms %s...", part_perms);
+ aclconfig_default_used = 0;
+
+ xperms = xmalloc (xperms_len);
+ xperms[0] = '\0';
+
+ /* use CVS_Username if set */
+ if (CVS_Username == NULL)
+ username = getcaller ();
+ else
+ username = CVS_Username;
+
+ /* no defined acl, no default acl in access file,
+ * or no access file at all */
+ if (part_perms == NULL) {
+ if (cvs_acl_default_permissions)
+ {
+ aclconfig_default_used = 1;
+ if (debug) fprintf (stderr, "default %s\n",
+ cvs_acl_default_permissions);
+ return (cvs_acl_default_permissions);
+ }
+ else {
+ if (debug) fprintf (stderr, "early %s\n", xperms);
+ return xperms;
+ }
+ }
+
+check_default:
+ founduser = findusername (part_perms, username);
+ foundall = strstr (part_perms, "ALL!");
+
+ if (debug) fprintf (stderr, "founduser=%s foundALL=%s\n",
+ founduser, foundall);
+ if (founduser)
+ {
+ char *usr;
+ char *per;
+
+ usr = strtok (founduser, "!\t");
+ per = strtok (NULL, ",\t");
+
+ xperms = xstrdup (per);
+ xperms_len = strlen (xperms);
+
+ userfound = 1;
+ }
+ else
+ {
+ if (debug) fprintf (stderr, "usesystemgroups=%d\n", use_system_groups);
+ if (use_system_groups) {
+ struct group *griter;
+ setgrent ();
+ while (griter = getgrent ())
+ {
+ char **users=griter->gr_mem;
+ int index = 0;
+ char *userchk = users [index++];
+ while(userchk != NULL) {
+ if(strcmp (userchk, username) == 0)
+ break;
+ userchk = users[index++];
+ }
+ if (debug) fprintf (stderr, "usercheck=%s\n", userchk);
+ if (userchk != NULL) {
+ char *grp;
+ if ((grp = findusername (part_perms, griter->gr_name)))
+ {
+ char *gperm = strtok (grp, "!\t");
+ if (debug) fprintf (stderr, "usercheck=%s, grp=%s\n",
+ userchk, grp);
+ gperm = strtok (NULL, ",\t");
+ xrealloc_and_strcat (&xperms, &xperms_len, gperm);
+
+ groupfound = 1;
+ }
+ }
+ }
+ endgrent ();
+ }
+ else if (use_cvs_groups) {
+ groupfp = open_groupfile ("r");
+ if (groupfp != NULL)
+ {
+ char *line = NULL;
+ char *grp;
+ char *gperm;
+ int read;
+
+ size_t line_allocated = 0;
+
+ while ((read = getline (&line, &line_allocated, groupfp)) >= 0)
+ {
+ if (line[0] == '#' || line[0] == '\0' || line[0] == '\n')
+ continue;
+
+ if (line[read - 1] == '\n')
+ line[--read] = '\0';
+
+ if (grp = findusername (part_perms,
+ findgroupname (line, username)))
+ {
+ gperm = strtok (grp, "!\t");
+ gperm = strtok (NULL, ",\t");
+ xrealloc_and_strcat (&xperms, &xperms_len, gperm);
+ groupfound = 1;
+ }
+ }
+
+ free (line);
+
+ if (fclose (groupfp) == EOF)
+ error (1, errno, "cannot close 'group' file");
+ }
+ }
+ }
+
+ if (foundall)
+ {
+ char *usr;
+ char *per;
+
+ usr = strtok (strstr (part_perms, "ALL!"), "!\t");
+ per = strtok (NULL, ",\t");
+
+ if (!default_checked)
+ default_perms_object = xstrdup (per);
+
+ if (xperms[0] == '\0')
+ {
+ xperms = xstrdup (per);
+ xperms_len = strlen (xperms);
+ }
+
+ free(foundall);
+
+ /* You don't free pointers from strtok()! */
+ //free(usr);
+ //free(per);
+ }
+
+ if (xperms[0] == '\0' && !default_checked && default_part_perms_accessfile)
+ {
+ part_perms = xstrdup (default_part_perms_accessfile);
+ default_checked = 1;
+
+ goto check_default;
+ }
+
+ if (xperms[0] != '\0' && strcmp (xperms, "x") == 0)
+ {
+ if (default_perms_object)
+ xperms = xstrdup (default_perms_object);
+ else if (default_part_perms_accessfile)
+ {
+ part_perms = default_part_perms_accessfile;
+ default_checked = 1;
+ goto check_default;
+ }
+ else if (cvs_acl_default_permissions)
+ {
+ aclconfig_default_used = 1;
+ xperms = xstrdup (cvs_acl_default_permissions);
+ }
+ }
+
+ if (xperms[0] == '\0' && cvs_acl_default_permissions)
+ {
+ aclconfig_default_used = 1;
+ xperms = xstrdup (cvs_acl_default_permissions);
+ }
+
+ if (debug) fprintf (stderr, "late %s\n", xperms);
+ return xperms;
+}
+
+
+int
+cvsacl (int argc, char **argv)
+{
+ char *chdirrepository;
+ int c;
+ int err = 0;
+ int usetag = 0;
+ int recursive = 0;
+
+ int which;
+ char *where;
+
+ is_racl = (strcmp (cvs_cmd_name, "racl") == 0);
+
+ if (argc == -1)
+ usage (is_racl ? racl_usage : acl_usage);
+
+ /* parse the args */
+ optind = 0;
+
+ while ((c = getopt (argc, argv, "dRr:l")) != -1)
+ {
+ switch (c)
+ {
+ case 'd':
+ debug++;
+ break;
+ case 'R':
+ recursive = 1;
+ break;
+ case 'r': // baris
+ tag = xstrdup (optarg);
+ break;
+ case 'l':
+ listacl = 1;
+ break;
+ case '?':
+ default:
+ usage (is_racl ? racl_usage : acl_usage);
+ break;
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < (is_racl ? 1 : 1))
+ usage (is_racl ? racl_usage : acl_usage);
+ if (listacl) {
+ if (strstr (argv[0], ":"))
+ usage (is_racl ? racl_usage : acl_usage);
+ } else {
+ if (!strstr (argv[0], ":"))
+ usage (is_racl ? racl_usage : acl_usage);
+ }
+
+
+#ifdef CLIENT_SUPPORT
+
+ if (current_parsed_root->isremote)
+ {
+ start_server ();
+ ign_setup ();
+
+ if(recursive)
+ send_arg ("-R");
+
+ if (listacl)
+ send_arg ("-l");
+
+ if(tag)
+ {
+ option_with_arg ("-r", tag);
+ }
+
+ send_arg ("--");
+
+ if (!listacl)
+ {
+ send_arg (argv[0]);
+
+ argc--;
+ argv++;
+ }
+
+ if (is_racl)
+ {
+ int i;
+ for (i = 0; i < argc; ++i)
+ send_arg (argv[i]);
+
+ send_to_server ("racl\012",0);
+ }
+ else
+ {
+ send_files (argc, argv, recursive, 0, SEND_NO_CONTENTS);
+ send_file_names (argc, argv, SEND_EXPAND_WILD);
+ send_to_server ("acl\012", 0);
+ }
+
+ return get_responses_and_close ();
+ }
+#endif
+
+#ifdef SERVER_SUPPORT
+
+ if (!listacl)
+ {
+ muser = strtok (argv[0], ":\t");
+ mperms = strtok (NULL, ":\t");
+
+ /* if set to 'default' */
+ if ((strlen (mperms) == 7) && (strncmp (mperms, "default", 7) == 0))
+ mperms = xstrdup ("x");
+
+ /* Check that the given permissions are valid. */
+ if (!given_perms_valid (mperms))
+ error (1,0,"Invalid permissions: `%s'", mperms);
+
+ argc--;
+ argv++;
+ }
+
+
+ if (!tag)
+ tag = xstrdup ("HEAD");
+
+ if (!strcasecmp (argv[0], "ALL"))
+ {
+ argv[0] = xstrdup (".");
+ defaultperms = 1;
+ if (!use_separate_acl_file_for_each_dir)
+ {
+ recursive = 0;
+ }
+
+ }
+
+ if (is_racl)
+ {
+ DBM *db;
+ int i;
+ db = open_module ();
+ for (i = 0; i < argc; i++)
+ {
+ err += do_module (db, argv[i], MISC, "ACL ing: ",
+ racl_proc, NULL, 0, !recursive, 0,
+ 0, NULL);
+ }
+ close_module (db);
+ }
+ else
+ {
+ err = racl_proc (argc + 1, argv - 1, NULL, NULL, NULL, 0, !recursive,
+ NULL, NULL);
+ }
+
+ return err;
+
+#endif
+}
+
+static int
+racl_proc (int argc, char **argv, char *xwhere, char *mwhere,
+ char *mfile, int shorten, int local, char *mname, char *msg)
+{
+ char *myargv[2];
+ int err = 0;
+ int which;
+ char *repository = NULL;
+ char *where;
+ char *obj;
+ size_t objlen = 0;
+
+ if (!use_cvs_acl)
+ {
+ error(1, 0, "CVSACL extension is not enabled, set `UseCVSACL=yes'"
+ " in aclconfig file");
+ }
+
+ if (is_racl)
+ {
+ repository = Xasprintf ("%s/%s", current_parsed_root->directory,
+ argv[0]);
+ where = xmalloc (strlen (argv[0]) + (mfile == NULL ? 0 :
+ strlen (mfile) + 1) + 1);
+ (void) strcpy (where, argv[0]);
+
+ /* if mfile isn't null, we need to set up to do only part of the
+ * module */
+ if (mfile != NULL)
+ {
+ char *cp;
+ char *path;
+
+ /* if the portion of the module is a path, put the dir part on
+ * repos */
+ if ((cp = strrchr (mfile, '/')) != NULL)
+ {
+ *cp = '\0';
+ (void) strcat (repository, "/");
+ (void) strcat (repository, mfile);
+ (void) strcat (where, "/");
+ (void) strcat (where, mfile);
+ mfile = cp + 1;
+ }
+
+ /* take care of the rest */
+ path = Xasprintf ("%s/%s", repository, mfile);
+ if (isdir (path))
+ {
+ /* directory means repository gets the dir tacked on */
+ (void) strcpy (repository, path);
+ (void) strcat (where, "/");
+ (void) strcat (where, mfile);
+ }
+ else
+ {
+ myargv[0] = argv[0];
+ myargv[1] = mfile;
+ argc = 2;
+ argv = myargv;
+ }
+ free (path);
+ }
+
+ /* cd to the starting repository */
+ if ( CVS_CHDIR (repository) < 0)
+ {
+ error (0, errno, "cannot chdir to %s", repository);
+ free (repository);
+ free (where);
+ return 1;
+ }
+
+ /* End section which is identical to patch_proc. */
+
+ which = W_REPOS | W_ATTIC;
+
+ if (argc > 1)
+ {
+ obj = Xasprintf ("%s/%s", repository, argv[1]);
+ }
+ else
+ {
+ obj = xstrdup(repository);
+ }
+ }
+ else
+ {
+ where = NULL;
+ which = W_LOCAL | W_REPOS | W_ATTIC;
+
+ obj = xstrdup (argv[1]);
+ }
+
+ if (isdir (obj))
+ acldir = 1;
+ else if (isfile (obj))
+ aclfile = 1;
+ else
+ error(1, 0, "no such file or directory");
+
+ free (obj);
+
+ if (listacl)
+ err = start_recursion (acllist_fileproc, NULL, acllist_dirproc, NULL,
+ NULL, argc - 1, argv + 1, local, which, 0, 0,
+ (char *) where, 1, repository);
+ else
+ err = start_recursion (acl_fileproc, NULL, acl_dirproc, NULL, NULL,
+ argc - 1, argv + 1, local, which, 0, 0,
+ (char *) where, 1, repository);
+
+ if (repository != NULL)
+ free (repository);
+
+ return err;
+}
+
+
+static int
+acl_fileproc (void *callerdat, struct file_info *finfo)
+{
+ char *filefullname;
+ char *founduserpart = NULL;
+ char *otheruserparts = NULL;
+ size_t otherslen = 0;
+
+ const char *frepository;
+ int foundline = 0;
+
+ char *line = NULL;
+ size_t line_allocated = 0;
+ int linelen;
+
+ char *wperms;
+ char *errmsg;
+
+ int pos;
+
+ if (!aclfile)
+ return 0;
+
+ frepository = Short_Repository (finfo->repository);
+
+ filefullname = Xasprintf("%s/%s", frepository, finfo->file);
+
+
+ if (!access_allowed (finfo->file, finfo->repository, tag, 8, &line, &pos,
+ 0))
+ error (1, 0, "You do not have acl admin rights on '%s'", frepository);
+
+ if (line != NULL)
+ {
+ char *part_type = NULL;
+ char *part_object = NULL;
+ char *part_tag = NULL;
+ char *part_perms = NULL;
+ char *userpart;
+
+ part_type = strtok (line, ":\t");
+ part_object = strtok (NULL, ":\t");
+ part_tag = strtok (NULL, ":\t");
+ part_perms = strtok (NULL, ":\t");
+
+ foundline = 1;
+ userpart = strtok (part_perms, ",\t");
+
+ do
+ {
+ if (strncmp (userpart, muser, strlen (muser)) == 0)
+ founduserpart = xstrdup (userpart);
+ else
+ {
+ if (otheruserparts != NULL)
+ {
+ xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
+ xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
+ }
+ else
+ {
+ otheruserparts = xstrdup (userpart);
+ otherslen = strlen (otheruserparts);
+ }
+ }
+ } while ((userpart = strtok (NULL, ",\t")) != NULL);
+
+ free (userpart);
+ }
+
+ wperms = make_perms (mperms, founduserpart, &errmsg);
+ if (wperms == NULL)
+ {
+ if (errmsg)
+ error (0, 0, "`%s' %s", filefullname, errmsg);
+ }
+ else
+ {
+ cvs_output ("X ", 0);
+ cvs_output (filefullname, 0);
+ cvs_output ("\n", 0);
+
+ write_perms (muser, wperms, founduserpart, foundline,
+ otheruserparts, "f", filefullname, tag, pos,
+ Short_Repository(finfo->repository));
+ }
+
+ free (line);
+ free (founduserpart);
+ free (otheruserparts);
+ free (wperms);
+ free (filefullname);
+
+ return 0;
+}
+
+static Dtype
+acl_dirproc (void *callerdat, const char *dir, const char *repos,
+ const char *update_dir, List *entries)
+{
+ const char *drepository;
+ char *founduserpart = NULL;
+ char *otheruserparts = NULL;
+ size_t otherslen = 0;
+ int foundline = 0;
+
+ char *line = NULL;
+ size_t line_allocated = 0;
+ int linelen;
+
+ int pos;
+
+ char *wperms;
+ char *errmsg;
+
+ if (!acldir)
+ return 0;
+
+ if (repos[0] == '\0')
+ repos = Name_Repository (dir, NULL);
+
+ if (!access_allowed (NULL, repos, tag, 8, &line, &pos, 0))
+ error (1, 0, "You do not have admin rights on '%s'",
+ Short_Repository (repos));
+
+ drepository = Short_Repository (repos);
+
+ if (line != NULL)
+ {
+ char *part_type = NULL;
+ char *part_object = NULL;
+ char *part_tag = NULL;
+ char *part_perms = NULL;
+ char *userpart;
+
+ part_type = strtok (line, ":\t");
+ part_object = strtok (NULL, ":\t");
+ part_tag = strtok (NULL, ":\t");
+ part_perms = strtok (NULL, ":\t");
+
+ foundline = 1;
+ userpart = strtok (part_perms, ",\t");
+
+ do
+ {
+ if (strncmp (userpart, muser, strlen (muser)) == 0)
+ founduserpart = xstrdup (userpart);
+ else
+ {
+ if (otheruserparts != NULL)
+ {
+ xrealloc_and_strcat (&otheruserparts, &otherslen, ",");
+ xrealloc_and_strcat (&otheruserparts, &otherslen, userpart);
+ }
+ else
+ {
+ otheruserparts = xstrdup (userpart);
+ otherslen = strlen (otheruserparts);
+ }
+ }
+ } while ((userpart = strtok (NULL, ",\t")) != NULL);
+ }
+
+ wperms = make_perms (mperms, founduserpart, &errmsg);
+ if (wperms == NULL)
+ {
+ if (errmsg)
+ error (0, 0, "`%s' %s", drepository, errmsg);
+ }
+ else
+ {
+ if (defaultperms)
+ {
+ cvs_output ("X ", 0);
+ cvs_output ("ALL", 0);
+ cvs_output ("\n", 0);
+ write_perms (muser, wperms, founduserpart, foundline,
+ otheruserparts, "d", "ALL", tag, pos, drepository);
+
+ }
+ else
+ {
+ cvs_output ("X ", 0);
+ cvs_output (drepository, 0);
+ cvs_output ("\n", 0);
+ write_perms (muser, wperms, founduserpart, foundline,
+ otheruserparts, "d", drepository, tag, pos,
+ drepository);
+ }
+ }
+
+ free (line);
+ free (founduserpart);
+ free (otheruserparts);
+ free (wperms);
+
+ return 0;
+}
+
+/* Open CVSROOT/access or defined CVSACLFileLocation file
+ * Open access file In each directory if UseSeparateACLFileForEachDir=yes
+ * returns file pointer to access file or NULL if access file not found */
+FILE *
+open_accessfile (char *fmode, const char *adir, char **fname)
+{
+ char *accessfile = NULL;
+ FILE *accessfp;
+
+ if (!use_separate_acl_file_for_each_dir)
+ {
+ if (cvs_acl_file_location == NULL)
+ {
+ accessfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
+ CVSROOTADM, CVSROOTADM_ACCESS);
+ }
+ else
+ {
+ accessfile = xstrdup(cvs_acl_file_location);
+ }
+ }
+ else
+ {
+ size_t accessfilelen = 0;
+ xrealloc_and_strcat (&accessfile, &accessfilelen,
+ current_parsed_root->directory);
+ xrealloc_and_strcat (&accessfile, &accessfilelen, "/");
+ xrealloc_and_strcat (&accessfile, &accessfilelen, adir);
+ xrealloc_and_strcat (&accessfile, &accessfilelen, "/access");
+ }
+
+ accessfp = CVS_FOPEN (accessfile, fmode);
+
+ if (fname != NULL)
+ *fname = xstrdup (accessfile);
+
+ free (accessfile);
+
+ return accessfp;
+}
+
+/* Open /etc/group file if UseSystemGroups=yes in config file
+ * Open CVSROOT/group file if UseCVSGroups=yes in config file
+ * Open group file if specified in CVSGroupsFileLocation
+ * returns group file pointer if UseSystemGroups=yes
+ * returns NULL if UseSystemGroups=no or group file not found */
+FILE *
+open_groupfile (char *fmode)
+{
+ char *groupfile;
+ FILE *groupfp;
+
+ if (use_cvs_groups)
+ {
+ if (cvs_groups_file_location != NULL)
+ {
+ groupfile = xstrdup (cvs_groups_file_location);
+ }
+ else
+ {
+ groupfile = Xasprintf("%s/%s/%s", current_parsed_root->directory,
+ CVSROOTADM, CVSROOTADM_GROUP);
+ }
+ }
+ else
+ {
+ return NULL;
+ }
+
+ groupfp = CVS_FOPEN (groupfile, "r");
+
+ if (groupfp == NULL)
+ error (0, 0, "cannot open file: %s", groupfile);
+
+ free (groupfile);
+
+ return groupfp;
+}
+
+
+/* Check whether given permissions are valid or not
+ * Returns 1 if permissions are valid
+ * Returns 0 if permissions are NOT valid */
+int
+given_perms_valid (const char *cperms)
+{
+ int cperms_len;
+ int retval;
+ int index, i;
+
+ if (cperms[0] == '+' || cperms[0] == '-')
+ index = 1;
+ else
+ index = 0;
+
+ cperms_len = strlen (cperms);
+
+ switch (cperms[index])
+ {
+ case 'x':
+ if ((cperms_len - index) == 1 && cperms_len == 1)
+ retval = 1;
+ else
+ retval = 0;
+ break;
+ case 'n':
+ if ((cperms_len - index) == 1 && cperms_len == 1)
+ retval = 1;
+ else
+ retval = 0;
+ break;
+ case 'p':
+ if ((cperms_len - index) == 1)
+ retval = 1;
+ else
+ retval = 0;
+ break;
+ case 'a':
+ if ((cperms_len - index) == 1)
+ retval = 1;
+ else
+ retval = 0;
+ break;
+ case 'r':
+ if ((cperms_len - index) == 1)
+ retval = 1;
+ else
+ retval = 0;
+ break;
+ case 'w':
+ if ((cperms_len - index) == 1)
+ retval = 1;
+ else
+ for (i = index + 1; i < cperms_len; i++)
+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'd')
+ retval = 1;
+ else
+ retval = 0;
+ break;
+ case 't':
+ if ((cperms_len - index) == 1)
+ retval = 1;
+ else
+ for (i = index + 1; i < cperms_len; i++)
+ if (cperms[i] == 'w' || cperms[i] == 'c' || cperms[i] == 'd')
+ retval = 1;
+ else
+ retval = 0;
+ break;
+ case 'c':
+ if ((cperms_len - index) == 1)
+ retval = 1;
+ else
+ for (i = index + 1; i < cperms_len; i++)
+ if (cperms[i] == 't' || cperms[i] == 'w' || cperms[i] == 'd')
+ retval = 1;
+ else
+ retval = 0;
+ break;
+ case 'd':
+ if ((cperms_len - index) == 1)
+ retval = 1;
+ else
+ for (i = index + 1; i < cperms_len; i++)
+ if (cperms[i] == 't' || cperms[i] == 'c' || cperms[i] == 'w')
+ retval = 1;
+ else
+ retval = 0;
+ break;
+ default:
+ retval = 0;
+ break;
+ }
+
+ return retval;
+}
+
+/* prepare permsissions string to be written to access file
+ * returns permissions or NULL if */
+char *
+make_perms (char *perms, char *founduserpart, char **xerrmsg)
+{
+ char *fperms;
+ size_t perms_len;
+ size_t fperms_len;
+
+ int i, j;
+ int err = 0;
+ char *errmsg = NULL;
+
+ char *retperms;
+ size_t retperms_len = 1;
+
+ retperms = xmalloc (retperms_len);
+ retperms[0] = '\0';
+
+ perms_len = strlen (perms);
+
+ if (perms[0] == '+' || perms[0] == '-')
+ {
+ if (founduserpart)
+ {
+ char *tempfperms;
+ size_t tempfperms_len;
+
+ char *temp;
+ int per = 0;
+ temp = strtok (founduserpart, "!\t");
+ fperms = strtok (NULL, "!\t");
+ fperms_len = strlen (fperms);
+
+ if (strncmp (fperms, "x", 1) == 0)
+ {
+ err = 1;
+ if (perms[0] == '+')
+ *xerrmsg = xstrdup ("cannot add default permission 'x'");
+ else
+ *xerrmsg = xstrdup ("cannot remove default permission 'x'");
+ }
+
+ /* go through perms */
+ for (i = 1; i < perms_len && !err; i++)
+ {
+ switch (perms[i])
+ {
+ case 'n':
+ err = 1;
+ break;
+ case 'p':
+ if (perms[0] == '+')
+ fperms = xstrdup ("p");
+ else if (perms[0] == '-')
+ {
+ fperms_len = 1;
+ fperms = xmalloc (fperms_len);
+ fperms[0] = '\0';
+ }
+ break;
+ case 'a':
+ for (j = 0; j < fperms_len; j++)
+ {
+ if (fperms[j] == 'p')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user have admin rights,"
+ " cannot use +/- permissions");
+ }
+ else if (fperms[j] == 'a' && perms[0] == '+')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user already has all ('a')"
+ " permission");
+ }
+ else if (fperms[j] != 'a' && perms[0] == '-')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user does not have all "
+ "('a') permission");
+ }
+ }
+ if (perms[0] == '+')
+ {
+ fperms = xstrdup ("a");
+ fperms_len = strlen (fperms);
+ }
+ else if (perms[0] == '-')
+ {
+ fperms_len = 1;
+ fperms = xmalloc (fperms_len);
+ fperms[0] = '\0';
+ }
+ break;
+ case 'r':
+ for (i = 0; i < fperms_len; i++)
+ {
+ if (fperms[i] == 'n' && perms[0] == '+')
+ {
+ fperms = xstrdup ("r");
+ fperms_len = strlen (fperms);
+ }
+ else if (fperms[i] == 'r' && perms[0] == '-')
+ {
+ fperms_len = 1;
+ fperms = xmalloc (fperms_len);
+ fperms[0] = '\0';
+ }
+ else if (perms[0] == '-')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user has other permissions,"
+ " cannot remove read ('r')"
+ " permission");
+ }
+ else
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user has other permissions,"
+ " cannot remove read ('r')"
+ " permission");
+ }
+ }
+ break;
+ case 'w':
+ {
+ tempfperms_len = 1;
+
+ tempfperms = xmalloc (tempfperms_len);
+ tempfperms[0] = '\0';
+
+ for (j = 0; j < fperms_len; j++)
+ {
+ if (fperms[j] == 't' || fperms[j] == 'c' ||
+ fperms[j] == 'd')
+ {
+ char *temp;
+ temp = xmalloc (2);
+ temp[0] = fperms[j];
+ temp[1] = '\0';
+
+ xrealloc_and_strcat (&tempfperms,
+ &tempfperms_len, temp);
+ free (temp);
+ }
+ else if (fperms[j] == 'a' || fperms[j] == 'p')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user has higher"
+ " permissions, cannot use"
+ " +/- write permissions");
+ }
+ else if (fperms[j] == 'n' || fperms[j] == 'r')
+ {
+ if (perms[0] == '-')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user does not have"
+ " write ('w')"
+ " permission");
+ }
+ }
+ else if (fperms[j] == 'w')
+ {
+ per = 1;
+ if (perms[0] == '+') {
+ err = 1;
+ *xerrmsg = xstrdup ("user already have"
+ " write ('w')"
+ "permission");
+ }
+ }
+ }
+
+ fperms = xstrdup (tempfperms);
+ fperms_len = strlen (fperms);
+ free (tempfperms);
+
+ if (!per && !err && (perms[0] == '-')) {
+ err = 1;
+ *xerrmsg = xstrdup ("user does not have write"
+ " ('w') permission");
+ }
+
+ if (perms[0] == '+')
+ {
+ xrealloc_and_strcat (&fperms, &fperms_len, "w");
+ }
+ }
+ break;
+ case 't':
+ {
+ tempfperms_len = 1;
+
+ tempfperms = xmalloc (tempfperms_len);
+ tempfperms[0] = '\0';
+
+ for (j = 0; j < fperms_len; j++)
+ {
+ if (fperms[j] == 'w' || fperms[j] == 'c' ||
+ fperms[j] == 'd')
+ {
+ char *temp;
+ temp = xmalloc (2);
+ temp[0] = fperms[j];
+ temp[1] = '\0';
+
+ xrealloc_and_strcat (&tempfperms,
+ &tempfperms_len, temp);
+ free (temp);
+ }
+ else if (fperms[j] == 'a' || fperms[j] == 'p')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user has higher"
+ " permissions, cannot use"
+ " +/- tag permissions");
+ }
+ else if (fperms[j] == 'n' || fperms[i] == 'r')
+ {
+ if (perms[0] == '-')
+ *xerrmsg = xstrdup ("user does not have tag"
+ " ('t') permission");
+ }
+ else if (fperms[j] == 't')
+ {
+ per = 1;
+ if (perms[0] == '+')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user already have tag"
+ " ('t') permission");
+ }
+ }
+ }
+
+ fperms = xstrdup (tempfperms);
+ fperms_len = strlen (fperms);
+ free (tempfperms);
+
+ if (!per && !err && (perms[0] == '-'))
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user does not have tag ('t')"
+ " permission");
+ }
+
+ if (perms[0] == '+')
+ {
+ xrealloc_and_strcat (&fperms, &fperms_len, "t");
+ }
+ }
+ break;
+ case 'c':
+ {
+ tempfperms_len = 1;
+
+ tempfperms = xmalloc (tempfperms_len);
+ tempfperms[0] = '\0';
+
+ for (j = 0; j < fperms_len; j++)
+ {
+ if (fperms[j] == 'w' || fperms[j] == 't' ||
+ fperms[j] == 'd')
+ {
+ char *temp;
+ temp = xmalloc (2);
+ temp[0] = fperms[j];
+ temp[1] = '\0';
+
+ xrealloc_and_strcat (&tempfperms,
+ &tempfperms_len, temp);
+ free (temp);
+ }
+ else if (fperms[j] == 'a' || fperms[j] == 'p')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user has higher"
+ " permissions, cannot use"
+ " +/- create permissions");
+ }
+ else if (fperms[j] == 'n' || fperms[i] == 'r')
+ {
+ if (perms[0] == '-')
+ err = 1;
+ *xerrmsg = xstrdup ("user does not have create"
+ " ('c') permission");
+ }
+ else if (fperms[j] == 'c')
+ {
+ per = 1;
+ if (perms[0] == '+') {
+ err = 1;
+ *xerrmsg = xstrdup ("user already have"
+ " create ('c')"
+ " permission");
+ }
+ }
+ }
+
+ fperms = xstrdup (tempfperms);
+ fperms_len = strlen (fperms);
+ free (tempfperms);
+
+ if (!per && !err && (perms[0] == '-')) {
+ err = 1;
+ *xerrmsg = xstrdup ("user does not have create"
+ " ('c') permission");
+ }
+
+ if (perms[0] == '+')
+ {
+ xrealloc_and_strcat (&fperms, &fperms_len, "c");
+ }
+ }
+ break;
+ case 'd':
+ {
+ tempfperms_len = 1;
+
+ tempfperms = xmalloc (tempfperms_len);
+ tempfperms[0] = '\0';
+
+ for (j = 0; j < fperms_len; j++)
+ {
+ if (fperms[j] == 'w' || fperms[j] == 'c' ||
+ fperms[j] == 't')
+ {
+ char *temp;
+ temp = xmalloc (2);
+ temp[0] = fperms[j];
+ temp[1] = '\0';
+
+ xrealloc_and_strcat (&tempfperms,
+ &tempfperms_len, temp);
+ free (temp);
+ }
+ else if (fperms[j] == 'a' || fperms[j] == 'p')
+ {
+ err = 1;
+ *xerrmsg = xstrdup ("user has higher"
+ " permissions, cannot use"
+ " +/- delete permissions");
+ }
+ else if (fperms[j] == 'n' || fperms[i] == 'r')
+ {
+ if (perms[0] == '-')
+ err = 1;
+ *xerrmsg = xstrdup ("user does not have delete"
+ " ('d') permission");
+ }
+ else if (fperms[j] == 'd')
+ {
+ per = 1;
+ if (perms[0] == '+') {
+ err = 1;
+ *xerrmsg = xstrdup ("user already have"
+ " delete ('d')"
+ " permission");
+ }
+ }
+ }
+
+ fperms = xstrdup (tempfperms);
+ fperms_len = strlen (fperms);
+ free (tempfperms);
+
+ if (!per && !err && (perms[0] == '-')) {
+ err = 1;
+ *xerrmsg = xstrdup ("user does not have delete"
+ " ('d') permission");
+ }
+
+ if (perms[0] == '+')
+ {
+ xrealloc_and_strcat (&fperms, &fperms_len, "d");
+ }
+ }
+ break;
+ default:
+ err = 1;
+ *xerrmsg = xstrdup ("error in 'access' file format");
+ break;
+ }
+
+ if (fperms[0] == '\0')
+ retperms = xstrdup ("none");
+ else
+ retperms = xstrdup (fperms);
+ }
+ }
+ else
+ {
+ err = 1;
+ *xerrmsg = xstrdup("user is not given any permissions to remove/add");
+ }
+ }
+ else
+ {
+ retperms = xstrdup (perms);
+ }
+
+ return (err ? NULL : retperms);
+}
+
+/* prepare and write resulting permissions to access file */
+static int
+write_perms (const char *user, const char *perms, const char *founduserpart,
+ int foundline, char *otheruserparts,
+ const char *part_type, const char *part_object,
+ const char *part_tag, int pos, const char *arepos)
+{
+ char *accessfile;
+ char *tmpaccessout;
+ FILE *accessfpin;
+ FILE *accessfpout;
+
+ char *newline = NULL;
+ size_t newlinelen = 1;
+ char *object;
+
+ char *line = NULL;
+ size_t line_allocated = 0;
+
+ newline = xmalloc (newlinelen);
+ newline[0] = '\0';
+
+ if (!strcasecmp (part_tag, "ALL"))
+ part_tag = "ALL";
+
+ /* strip any trailing slash if found */
+ object = xstrdup (part_object);
+ if (object[strlen (object) - 1] == '/')
+ object[strlen (object) - 1] = '\0';
+
+ /* first parts, part type, object, and tag */
+ xrealloc_and_strcat (&newline, &newlinelen, part_type);
+ xrealloc_and_strcat (&newline, &newlinelen, ":");
+ xrealloc_and_strcat (&newline, &newlinelen, object);
+ xrealloc_and_strcat (&newline, &newlinelen, ":");
+ xrealloc_and_strcat (&newline, &newlinelen, part_tag);
+ xrealloc_and_strcat (&newline, &newlinelen, ":");
+
+ if (strncmp (perms, "none", 4) != 0)
+ {
+ xrealloc_and_strcat (&newline, &newlinelen, user);
+ xrealloc_and_strcat (&newline, &newlinelen, "!");
+ xrealloc_and_strcat (&newline, &newlinelen, perms);
+ if (otheruserparts != NULL)
+ xrealloc_and_strcat (&newline, &newlinelen, ",");
+ }
+
+ if (otheruserparts != NULL)
+ {
+ if (otheruserparts[strlen (otheruserparts) - 1] == '\n')
+ otheruserparts[strlen (otheruserparts) - 1] = '\0';
+
+ xrealloc_and_strcat (&newline, &newlinelen, otheruserparts);
+ }
+
+ xrealloc_and_strcat (&newline, &newlinelen, ":");
+
+ if (foundline)
+ {
+ accessfpout = cvs_temp_file (&tmpaccessout);
+ if (accessfpout == NULL)
+ error (1, errno, "cannot open temporary file: %s", tmpaccessout);
+
+ accessfpin = open_accessfile ("r", arepos, &accessfile);
+ if (accessfpout == NULL)
+ error (1, errno, "cannot open access file: %s", accessfile);
+
+ while (getline (&line, &line_allocated, accessfpin) >= 0)
+ {
+ if (pos != ftell (accessfpin))
+ {
+ if (fprintf (accessfpout, "%s", line) < 0)
+ error (1, errno, "writing temporary file: %s", tmpaccessout);
+ }
+ else
+ {
+ if (fprintf (accessfpout, "%s\n", newline) < 0)
+ error (1, errno, "writing temporary file: %s", tmpaccessout);
+ }
+
+ }
+ if (fclose (accessfpin) == EOF)
+ error (1, errno, "cannot close access file: %s", accessfile);
+
+ if (fclose (accessfpout) == EOF)
+ error (1, errno, "cannot close temporary file: %s", tmpaccessout);
+
+ if (CVS_UNLINK (accessfile) < 0)
+ error (0, errno, "cannot remove %s", accessfile);
+
+ copy_file (tmpaccessout, accessfile);
+
+ if (CVS_UNLINK (tmpaccessout) < 0)
+ error (0, errno, "cannot remove temporary file: %s", tmpaccessout);
+ }
+ else
+ {
+ accessfpout = open_accessfile ("r+", arepos, &accessfile);
+
+ if (accessfpout == NULL)
+ {
+ if (existence_error (errno))
+ {
+ accessfpout = open_accessfile ("w+", arepos, &accessfile);
+ }
+ if (accessfpout == NULL)
+ error (1, errno, "cannot open access file: %s", accessfile);
+ }
+ else {
+ if (fseek (accessfpout, 0, 2) != 0)
+ error (1, errno, "cannot fseek access file: %s", accessfile);
+ }
+
+ if (fprintf (accessfpout, "%s\n", newline) < 0)
+ error (1, errno, "writing access file: %s", accessfile);
+
+ if (fclose (accessfpout) == EOF)
+ error (1, errno, "cannot close access file: %s", accessfile);
+ }
+
+ free (line);
+ free (newline);
+
+ chmod (accessfile, 0644);
+
+ return 0;
+}
+
+static int
+acllist_fileproc (void *callerdat, struct file_info *finfo)
+{
+ char *filefullname;
+ const char *frepository;
+ char *line = NULL;
+ int pos;
+
+ if (!aclfile)
+ return 0;
+
+ frepository = Short_Repository (finfo->repository);
+
+ filefullname = Xasprintf("%s/%s", frepository, finfo->file);
+
+ /* check that user, which run acl/racl command, has admin permisson,
+ * and also return the line with permissions from access file. */
+ if (!access_allowed (finfo->file, finfo->repository, tag, 5, &line, &pos,
+ 0))
+ error (1, 0, "You do not have admin rights on '%s'", frepository);
+
+ acllist_print (line, filefullname);
+
+ free (filefullname);
+
+ return 0;
+}
+
+static Dtype
+acllist_dirproc (void *callerdat, const char *dir, const char *repos,
+ const char *update_dir, List *entries)
+{
+ char *line = NULL;
+ const char *drepository;
+ int pos;
+
+ if (repos[0] == '\0')
+ repos = Name_Repository (dir, NULL);
+
+ if (!acldir)
+ return 0;
+
+ drepository = Short_Repository (repos);
+
+ /* check that user, which run acl/racl command, has admin permisson,
+ * and also return the line with permissions from access file. */
+ if (!access_allowed (NULL, repos, tag, 5, &line, &pos, 0))
+ error (1, 0, "You do not have admin rights on '%s'", drepository);
+
+ acllist_print (line, drepository);
+
+ return 0;
+}
+
+/* Prints permissions to screen with -l option */
+void
+acllist_print (char *line, const char *obj)
+{
+ char *temp;
+ int c = 0;
+ int def = 0;
+
+ char *printedusers[255];
+ printedusers[0] = NULL;
+
+ if (line != NULL)
+ {
+ temp = strtok (line, ":\t");
+
+ if (acldir)
+ cvs_output ("d ", 0);
+ else if (aclfile)
+ cvs_output ("f ", 0);
+
+ temp = strtok (NULL, ":\t");
+
+ cvs_output(obj, 0);
+ cvs_output (" | ", 0);
+
+ temp = strtok (NULL, ":\t");
+ cvs_output (temp, 0);
+ cvs_output (" | ", 0);
+
+ while ((temp = strtok (NULL, "!\t")) != NULL)
+ {
+ if (strncmp (temp, ":", 1) == 0)
+ break;
+
+ if (strcmp (temp, "ALL") == 0)
+ {
+ temp = strtok (NULL, ",\t");
+ continue;
+ }
+
+ cvs_output (temp, 0);
+ cvs_output (":", 0);
+
+ while (printedusers[c] != NULL)
+ c++;
+
+ printedusers[c] = xstrdup (temp);
+ c++;
+ printedusers[c] = NULL;
+
+ temp = strtok (NULL, ",\t");
+
+ if (temp != NULL && temp[strlen (temp) - 2] == ':')
+ temp[strlen (temp) - 2] = '\0';
+
+ cvs_output (temp, 0);
+ cvs_output (" ", 0);
+ }
+
+ if (default_perms_object)
+ {
+ cvs_output ("| defaults ", 0);
+ cvs_output ("ALL:", 0);
+ cvs_output (default_perms_object, 0);
+ def = 1;
+ }
+ if (default_part_perms_accessfile)
+ {
+ size_t i;
+ i = strlen (default_part_perms_accessfile);
+ xrealloc_and_strcat (&default_part_perms_accessfile, &i, ",");
+
+ free (line);
+ line = xstrdup (default_part_perms_accessfile);
+
+ if (!def)
+ cvs_output ("| defaults ", 0);
+ else
+ cvs_output (" ", 0);
+
+ temp = strtok (line, "!\t");
+ cvs_output (temp, 0);
+ cvs_output (":", 0);
+
+ temp = strtok (NULL, ",\t");
+
+ cvs_output (temp, 0);
+ cvs_output (" ", 0);
+
+ while ((temp = strtok (NULL, "!\t")) != NULL)
+ {
+ int printed = 0;
+ int c2 = 0;
+ while (printedusers[c2] != NULL && printed == 0)
+ {
+ if (strcmp (printedusers[c2], temp) == 0)
+ {
+ printed = 1;
+ break;
+ }
+ c2++;
+ }
+
+ if (printed == 0)
+ {
+ cvs_output (temp, 0);
+ cvs_output (":", 0);
+ }
+
+ temp = strtok (NULL, ",\t");
+
+ if (temp[strlen (temp) - 2] == ':')
+ temp[strlen (temp) - 2] = '\0';
+
+ if (printed == 0)
+ {
+ cvs_output (temp, 0);
+ cvs_output (" ", 0);
+ }
+ }
+ def = 1;
+ }
+ else if (cvs_acl_default_permissions)
+ {
+ cvs_output ("| defaults ", 0);
+ cvs_output ("ALL: ", 0);
+ cvs_output (cvs_acl_default_permissions, 0);
+ }
+ }
+ else
+ {
+ if (acldir)
+ cvs_output ("d ", 0);
+ else if (aclfile)
+ cvs_output ("f ", 0);
+ cvs_output (obj, 0);
+ cvs_output (" | ", 0);
+ cvs_output (tag, 0);
+ cvs_output (" | ", 0);
+
+ if (default_perms_object)
+ {
+ cvs_output ("| defaults ", 0);
+ cvs_output ("ALL:", 0);
+ cvs_output (default_perms_object, 0);
+ def = 1;
+ }
+ if (default_part_perms_accessfile)
+ {
+ free (line);
+ line = xstrdup (default_part_perms_accessfile);
+
+ if (!def)
+ cvs_output ("| defaults ", 0);
+ else
+ cvs_output (" ", 0);
+
+ temp = strtok (line, "!\t");
+ cvs_output (temp, 0);
+ cvs_output (":", 0);
+
+ temp = strtok (NULL, ",\t");
+
+ if (temp[strlen (temp) - 2] == ':')
+ temp[strlen (temp) - 2] = '\0';
+
+ cvs_output (temp, 0);
+ cvs_output (" ", 0);
+
+ while ((temp = strtok (NULL, "!\t")) != NULL)
+ {
+ cvs_output (temp, 0);
+ cvs_output (":", 0);
+
+ if ((temp = strtok (NULL, ",\t")) != NULL)
+ {
+ if (temp[strlen (temp) - 2] == ':')
+ temp[strlen (temp) - 2] = '\0';
+
+ cvs_output (temp, 0);
+ cvs_output (" ", 0);
+ }
+ }
+ cvs_output ("\n", 0);
+ }
+ else if (cvs_acl_default_permissions)
+ {
+ cvs_output ("| defaults ", 0);
+ cvs_output ("ALL: ", 0);
+ cvs_output (cvs_acl_default_permissions, 0);
+ }
+ else
+ cvs_output ("default:p (no perms)", 0);
+ }
+ cvs_output ("\n", 0);
+
+ while (c >= 0) {
+ free (printedusers[c]);
+ c--;
+ }
+
+ free (line);
+}
+
+/* find username
+ * returns username with its permissions if user found
+ * returns NULL if user not found */
+char *findusername (const char *string1, const char *string2)
+{
+ char *tmp1, *tmp2;
+
+ if (string1 != NULL && string2 != NULL)
+ {
+ tmp1 = xstrdup (string1);
+ tmp2 = strtok (tmp1, ",\t");
+
+ do
+ {
+ if (strncmp (tmp2, string2, strlen (string2)) == 0 &&
+ tmp2[strlen (string2)] == '!')
+ {
+ return tmp2;
+ }
+ tmp2 = strtok (NULL, ",\t");
+ }
+ while (tmp2 != NULL);
+
+ free (tmp1);
+ free (tmp2);
+
+ return NULL;
+ }
+ else
+ return NULL;
+}
+
+/* find user name in group file
+ * returns group name if user found
+ * returns NULL if user not found */
+char *findgroupname (const char *string1, const char *string2)
+{
+ char *tmp1, *tmp2;
+ char *grpname;
+
+ if (string1 != NULL && string2 != NULL)
+ {
+ tmp1 = xstrdup (string1);
+ grpname = strtok (tmp1, ":\t");
+
+ while (tmp2 = strtok(NULL, ",\t"))
+ {
+ if (strcmp (tmp2, string2) == 0)
+ {
+ return grpname;
+ }
+ }
+
+ free (tmp1);
+ free (tmp2);
+
+ return NULL;
+ }
+ else
+ return NULL;
+}