/*
* Copyright (c) 1992, Brian Berliner and Jeff Polk
* Copyright (c) 1989-1992, Brian Berliner
*
* You may distribute under the terms of the GNU General Public License as
* specified in the README file that comes with the CVS 1.4 kit.
*
* lsacl
*
* Shows the current permissions
*/
#include "cvs.h"
#include "fileattr.h"
static int is_rlsacl;
static const char *const lsacl_usage[] =
{
"Usage: %s %s [-d] [-R] [file or directory...]\n",
"\t-d\tShow directories only\n",
"\t-R\tRecurse unto subdirectories\n",
NULL
};
static const char *const rlsacl_usage[] =
{
"Usage: %s %s [-d] [-R] [module...]\n",
"\t-d\tShow directories only\n",
"\t-R\tRecurse unto subdirectories\n",
NULL
};
static Dtype lsacl_dirproc (void *callerdat, char *dir, char *repos, char *update_dir, List *entries, const char *virtual_repository, Dtype hint);
static int lsacl_fileproc(void *callerdat, struct file_info *finfo);
static int rlsacl_proc(int argc, char **argv, const char *xwhere,
const char *mwhere, const char *mfile, int shorten,
int local_specified, const char *mname, const char *msg);
int lsacl (int argc, char **argv)
{
int c;
int err = 0;
int local = 1;
int directories_only = 0;
is_rlsacl = !strcmp(command_name,"rlsacl");
if (argc == -1)
usage (is_rlsacl?rlsacl_usage:lsacl_usage);
optind = 0;
while ((c = getopt(argc, argv, "+dR")) != -1)
{
switch (c)
{
case 'd':
directories_only = 1;
break;
case 'R':
local = 0;
break;
case '?':
default:
usage (lsacl_usage);
break;
}
}
argc -= optind;
argv += optind;
if (argc < 0)
usage (is_rlsacl?rlsacl_usage:lsacl_usage);
if (current_parsed_root->isremote)
{
if(is_rlsacl)
{
if (!supported_request ("rlsacl"))
error (1, 0, "server does not support rlsacl");
}
else
{
if (!supported_request ("lsacl"))
error (1, 0, "server does not support lsacl");
}
if(!local)
send_arg("-R");
if(directories_only)
send_arg("-d");
send_arg("--");
if (is_rlsacl)
{
int i;
for (i = 0; i < argc; i++)
send_arg (argv[i]);
send_to_server ("rlsacl\n", 0);
}
else
{
send_file_names (argc, argv, SEND_EXPAND_WILD);
send_files (argc, argv, local, 0, SEND_NO_CONTENTS);
send_to_server ("lsacl\n", 0);
}
return get_responses_and_close ();
}
if(!acl_mode)
error(1,0,"Access control is disabled on this repository.");
if (is_rlsacl)
{
DBM *db;
int i;
db = open_module ();
if(!argc)
{
err += do_module (db, ".", MISC, "Listing", rlsacl_proc,
(char *) NULL, 0, local, 0, 0, (char *) NULL);
}
else
{
for (i = 0; i < argc; i++)
{
err += do_module (db, argv[i], MISC, "Listing", rlsacl_proc,
(char *) NULL, 0, local, 0, 0, (char *) NULL);
}
}
close_module (db);
}
else
{
/* start the recursion processor */
err = start_recursion (directories_only?NULL:lsacl_fileproc, (FILESDONEPROC) NULL,
(PREDIRENTPROC) NULL, lsacl_dirproc, (DIRLEAVEPROC) NULL, NULL,
argc, argv, local,
W_LOCAL, 0, 1, (char *) NULL, NULL, 1, NULL);
}
return (err);
}
static void acl_details(XmlHandle_t acl,const char *type)
{
XmlHandle_t h=fileattr_find(acl,type);
const char *d,*i;
if(h)
{
d=fileattr_getvalue(h,"@deny");
i=fileattr_getvalue(h,"@inherit");
if(!strcmp(type,"all") && (d && atoi(d)))
{
type="none";
d=NULL;
}
printf("\t%s",type);
if((d && atoi(d)) || (i && !atoi(i)))
{
printf("(");
if(d && atoi(d))
{
printf("deny");
if(i && atoi(i))
printf(",");
}
if(i&&atoi(i))
{
printf("noinherit");
}
printf(")");
}
printf("\n");
}
}
static void show_acl(XmlHandle_t acl)
{
while(acl)
{
const char *user = fileattr_getvalue(acl,"@user");
const char *branch = fileattr_getvalue(acl,"@branch");
const char *merge = fileattr_getvalue(acl,"@merge");
const char *priority = fileattr_getvalue(acl,"@priority");
const char *message = fileattr_getvalue(acl,"message");
const char *comma="";
printf("\n");
if(user)
{
printf("user=%s",user);
comma=",";
}
if(branch)
{
printf("%sbranch=%s",comma,branch);
comma=",";
}
if(merge)
{
printf("%smerge=%s",comma,merge);
}
if(!user && !branch && !merge)
printf("<default>");
if(priority)
printf(",priority=%s",priority);
if(message)
printf(",message=%s",message);
printf("\n");
acl_details(acl,"all");
acl_details(acl,"read");
acl_details(acl,"write");
acl_details(acl,"create");
acl_details(acl,"tag");
acl_details(acl,"control");
acl = fileattr_next(acl);
}
}
/*
* Show file ACL
*/
static Dtype lsacl_dirproc (void *callerdat, char *dir, char *repos, char *update_dir, List *entries, const char *virtual_repository, Dtype hint)
{
const char *owner;
XmlHandle_t acl;
if(hint!=R_PROCESS)
return hint;
owner = fileattr_getvalue(NULL,"directory/owner");
if(is_rlsacl && !strcmp(update_dir,"."))
update_dir="<root>";
printf("Directory: %s\n",update_dir);
printf("Owner: %s\n",(owner&&*owner)?owner:"<not set>");
acl = fileattr_find(NULL,"directory/acl");
show_acl(acl);
return R_PROCESS;
}
int lsacl_fileproc(void *callerdat, struct file_info *finfo)
{
XmlHandle_t acl;
acl = fileattr_find(NULL,"file[@name=F'%s']/acl",finfo->file);
if(acl)
{
printf("File: %s\n",finfo->file);
show_acl(acl);
}
return 0;
}
static int rlsacl_proc(int argc, char **argv, const char *xwhere,
const char *mwhere, const char *mfile, int shorten,
int local_specified, const char *mname, const char *msg)
{
/* Begin section which is identical to patch_proc--should this
be abstracted out somehow? */
char *myargv[2];
int err = 0;
char *repository, *mapped_repository;
char *where;
repository = (char*)xmalloc (strlen (current_parsed_root->directory) + strlen (argv[0])
+ (mfile == NULL ? 0 : strlen (mfile) + 1) + 2);
(void) sprintf (repository, "%s/%s", current_parsed_root->directory, argv[0]);
where = (char*)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 = (char*)xmalloc (strlen (repository) + strlen (mfile) + 5);
(void) sprintf (path, "%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] = (char*)mfile;
argc = 2;
argv = myargv;
}
xfree (path);
}
mapped_repository = map_repository(repository);
/* cd to the starting repository */
if ( CVS_CHDIR (mapped_repository) < 0)
{
error (0, errno, "cannot chdir to %s", fn_root(repository));
xfree (repository);
xfree (mapped_repository);
return (1);
}
xfree (repository);
/* End section which is identical to patch_proc. */
err = start_recursion (lsacl_fileproc, (FILESDONEPROC) NULL, (PREDIRENTPROC) NULL, lsacl_dirproc,
(DIRLEAVEPROC) NULL, NULL,
argc - 1, argv + 1, local_specified, W_REPOS, 0, 1,
where, mapped_repository, 1, NULL);
xfree (mapped_repository);
return err;
}
syntax highlighted by Code2HTML, v. 0.9.1