archie/prospero/server/shadowcvt.c
2024-05-27 16:13:40 +02:00

389 lines
14 KiB
C

/*
* Copyright (c) 1989, 1990, 1991 by the University of Washington
* Copyright (c) 1992, 1993 by the University of Southern California
*
* For copying and distribution information, please see the files
* <uw-copyright.h> and <usc-copyr.h>
*/
#include <uw-copyright.h>
#include <usc-copyr.h>
#include <pfs.h>
#include <pserver.h>
#include <pprot.h>
#include <pparse.h>
#include <stdio.h>
#ifndef MAXPATHLEN
#ifdef CONFLICT_BETWEEN_DEFINITION_OF_NULL_IN_SYS_PARAM_H_AND_STDDEF_H
#undef NULL
#endif /* #ifdef CONFLICT... */
#include <sys/param.h> /* XXX This should Change. MAXPATHLEN is too
UNIX-specific. It is almost always 1024,
but we should use MAX_VPATH instead. */
#ifdef CONFLICT_BETWEEN_DEFINITION_OF_NULL_IN_SYS_PARAM_H_AND_STDDEF_H
#ifndef NULL
#include <stddef.h>
#endif /* #ifndef NULL */
#endif /* #ifdef CONFLICT... */
#endif /* #ifndef MAXPATHLEN */
extern char *rindex();
/* These are used by some other routines. We don't ever actually use these
definitions, but functions that we call refer to them, although they
never actually make it into the files we're converting. */
char *aftpdir = "";
char shadow[MAXPATHLEN] = PSRV_FSHADOW;
char dirshadow[MAXPATHLEN] = DSHADOW;
char dircont[MAXPATHLEN] = DCONTENTS;
char pfsdat[MAXPATHLEN] = PSRV_FSTORAGE;
char hostwport[MAXPATHLEN+30] = "THIS SHOULD NOT EVER BE USED; hostwport[]";
/* Host name w/ port if non-standard */
/* shadowcvt.c */
/* Convert v1 format shadow directory files to v5 format. */
/* read shadowcvt.doc before running this program. */
main(argc,argv)
int argc;
char *argv[];
{
int numconv = 0; /* How many files converted successfully? */
char line[MAXPATHLEN];
extern int fseek();
/* server initialization routines. Needed to set stuff to files.*/
qoprintf = srv_qoprintf;
stdio_fseek = fseek;
if (argc != 3) {
fputs("shadowcvt: usage: shadowcvt old-directory \
new-directory < file-name-listing\n", stderr);
exit(1);
}
/* While there's a line with a single filename on it. */
while(scanf(" %s ", line) == 1) {
char infile[MAXPATHLEN], outfile[MAXPATHLEN], outdir[MAXPATHLEN] ;
FILE *in, *out;
char *slashp; /* pointer to last slash in string. */
assert(qsprintf(infile, sizeof infile, "%s/%s", argv[1], line)
<= sizeof infile);
assert(qsprintf(outfile, sizeof outfile, "%s/%s", argv[2], line)
<= sizeof outfile);
strcpy(outdir,outfile);
if ((slashp = rindex(outdir, '/')) == NULL) {
fprintf(stderr, "Can't find a last component in the output file \
%s. Something is very wrong! Aborting execution!\n", outdir);
exit(1);
}
*slashp = '\0';
/* create directory for output file */
if(mkdirs(outdir)) {
fprintf(stderr,
"Couldn't create a directory to hold the output file %s. \
Aborting.", outfile);
exit(1);
}
/* open infile and outfile */
if ((in = locked_fopen(infile, "r")) == NULL) {
fprintf(stderr, "Couldn't open input file %s; aborting \
execution!\n", infile);
exit(1);
}
if ((out = locked_fopen(outfile, "w")) == NULL) {
fprintf(stderr," Couldn't open output file %s;aborting \
execution!\n", outfile);
locked_fclose_A(in,infile,TRUE);
exit(1);
}
if(cvt_dir(infile, in, outfile, out)) {
fprintf(stderr, "Continuing to attempt to convert directory \
information.\n");
} else {
numconv++;
}
locked_fclose_A(in,infile,TRUE);
locked_fclose_A(out,outfile,FALSE);
}
exit(0);
}
static TOKEN tokenize();
static int fdsrdir_v1(char vfs_dirname[], FILE *in, VDIR dir);
int convert_v1_ltype(char l_type[], VLINK cur_link);
cvt_dir(infile, inf, outfile, outf)
char infile[]; /* for reporting error messages */
char outfile[];
FILE *inf, *outf;
{
VDIR_ST dir_st;
VDIR dir = &dir_st;
vdir_init(dir);
/* Read in the directory. */
if (fdsrdir_v1(infile, inf, dir) == 0) {
return fdswdir_v5(outf, dir);
}
RETURNPFAILURE;
}
static TOKEN
tokenize(s)
char *s;
{
TOKEN retval;
char buf[MAX_DIR_LINESIZE];
int tmp = qsscanf(s, "%!!s %r", buf, sizeof buf, &s);
if (tmp < 0)
internal_error("Buffer overflow!");
if (tmp == 0)
return NULL;
if ((retval = tkalloc(buf)) == NULL)
internal_error("tkalloc() out of memory!");
if (tmp == 2)
retval->next = tokenize(s);
return retval;
}
/* Read in a directory. Complaints to stderr. */
static int fdsrdir_v1(char vfs_dirname[], FILE *vfs_dir, VDIR dir)
{
char line[MAX_DIR_LINESIZE];
VLINK cur_link = NULL;
ACL cur_acl = NULL;
ACL prev_acl = NULL;
int tmp;
char truefalse[16];
int bad_link = 0; /* set to 1 if this link is bad and the ACL and
ATTRIBUTEs associated with it should be
skipped. */
int retval = PSUCCESS;
while(fgets(line,MAX_DIR_LINESIZE,vfs_dir)) {
switch(*line) {
case 'V':
tmp = sscanf(line,"VERSION %d",&(dir->version));
if(tmp != 1) {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
}
break;
case 'M': /* Magic Number */
tmp = sscanf(line,"MAGIC-NUMBER %d",&(dir->magic_no));
if(tmp != 1) {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
}
break;
case 'I':
tmp = sscanf(line,"INCLUDE-NATIVE %s",truefalse);
dir->inc_native = VDIN_INCLNATIVE;
if((*truefalse == 'F') || (*truefalse == 'f'))
dir->inc_native = VDIN_NONATIVE;
/* REAL-ONLY - Do not include . and .. */
if((*truefalse == 'R') || (*truefalse == 'r'))
dir->inc_native = VDIN_INCLREAL;
if(tmp != 1) {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
}
break;
case 'A': {
#if 1
char a_acetype[MAX_DIR_LINESIZE];
#else
char a_acltype[MAX_DIR_LINESIZE];
#endif
char a_atype[MAX_DIR_LINESIZE];
char a_rights[MAX_DIR_LINESIZE];
char *p_principals;
extern char *acltypes[];
if (strncmp(line, "ACL ", 4) && bad_link)
break;
cur_acl = acalloc();
/* Code partly taken from parse_owner(). */
p_principals = NULL;
/* V1 dswdir() always wrote at least 3 elements. */
if(qsscanf(line, "ACL %'!!s %'!!s %'!!s %r",
a_acetype, sizeof a_acetype, a_atype, sizeof a_atype,
a_rights, sizeof a_rights, &p_principals) < 3) {
fprintf(stderr,"Bad directory format %s: less than 3 \
arguments to an ACL entry (skipping this ACL line, but converting the rest of \
the directory): %s",
vfs_dirname,line,0);
acfree(cur_acl);
break;
}
for(cur_acl->acetype = 0;acltypes[cur_acl->acetype];
(cur_acl->acetype)++) {
if(strequal(acltypes[cur_acl->acetype],a_acetype))
break;
}
if(acltypes[cur_acl->acetype] == NULL) {
fprintf(stderr,"Bad directory format %s: \
couldn't find acl type %s (skipping this ACL line, but converting the rest of \
the directory): %s",
vfs_dirname,a_acetype, line,0);
acfree(cur_acl);
break;
}
cur_acl->atype = stcopyr(a_atype, cur_acl->atype);
cur_acl->rights = stcopyr(a_rights,cur_acl->rights);
cur_acl->principals = tokenize(unquote(p_principals));
if(prev_acl) {
prev_acl->next = cur_acl;
cur_acl->previous = prev_acl;
}
else if(cur_link) cur_link->acl = cur_acl;
else dir->dacl = cur_acl;
prev_acl = cur_acl;
}
break;
case 'L': {
char l_name[MAX_DIR_LINESIZE];
char l_type[MAX_DIR_LINESIZE];
char l_htype[MAX_DIR_LINESIZE];
char l_host[MAX_DIR_LINESIZE];
char l_ntype[MAX_DIR_LINESIZE];
char l_fname[MAX_DIR_LINESIZE];
prev_acl = NULL; /* So next acl entry is for a new link */
bad_link = 0; /* assume this link is
good until proven guilty :) */
cur_link = vlalloc();
cur_link->f_magic_no = 0; /* in case not set */
tmp = qsscanf(line,
"LINK %'s %c %s %d %*d %s %'s %s %'s %d %d",
l_name, &(cur_link->linktype), l_type,
&(cur_link->dest_exp),
/* &(cur_link->link_exp), */
l_htype,l_host,
l_ntype,l_fname,
&(cur_link->version),
&(cur_link->f_magic_no));
if(tmp >= 9) {
cur_link->name = stcopy(l_name);
cur_link->target = stcopyr(l_type, cur_link->target);
if(convert_v1_ltype(l_type, cur_link)) {
bad_link = 1;
fprintf(stderr, "Directory %s: Did not understand LINK of \
type %s (skipping this link and associated information, but converting the \
rest of the directory): %s", vfs_dirname, l_type, line);
vlfree(cur_link); cur_link = NULL;
break;
}
stfree(cur_link->hosttype); /* Should punt if same */
cur_link->hosttype = stcopy(l_htype);
cur_link->host = stcopy(l_host);
stfree(cur_link->hsonametype); /* Should punt if same */
cur_link->hsonametype = stcopy(l_ntype);
cur_link->hsoname = stcopy(l_fname);
/* if ul, then vl_insert will call ul_insert */
vl_insert(cur_link,dir,VLI_ALLOW_CONF);
/* No need to free cur_link once inserted into dir */
}
else {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
vlfree(cur_link); cur_link = NULL;
}
}
break;
case 'F': { /* Filter attached to previous link */
char f_type;
char f_htype[MAX_DIR_LINESIZE];
char f_host[MAX_DIR_LINESIZE];
char f_ntype[MAX_DIR_LINESIZE];
char f_fname[MAX_DIR_LINESIZE];
int f_vers = 0;
int f_mno = 0;
char f_args[MAX_DIR_LINESIZE];
FILTER cur_fil;
if (strnequal(line, "FILTER ", 7) && bad_link)
break;
if(!cur_link) {
fprintf(stderr, "No reference to previous link. Can't add filter %s: %s",
vfs_dirname,line,0);
break;
}
cur_fil = flalloc();
cur_fil->execution_location = FIL_CLIENT;
cur_fil->link = vlalloc();
f_vers = 0; f_mno = 0;
tmp = sscanf(line,"FILTER %c %s %s %s %s %d %d ARGS ' %[^']",
&f_type, f_htype, f_host, f_ntype, f_fname,
&f_vers, &f_mno, f_args);
if(tmp >= 5) {
cur_fil->pre_or_post = FIL_POST;
switch(f_type) {
case 'd':
cur_fil->pre_or_post = FIL_PRE;
case 'D':
cur_fil->type = FIL_DIRECTORY;
break;
case 'h':
cur_fil->pre_or_post = FIL_PRE;
case 'H':
cur_fil->type = FIL_HIERARCHY;
break;
case 'O':
cur_fil->type = FIL_OBJECT;
break;
case 'U':
cur_fil->type = FIL_UPDATE;
break;
default:
fprintf(stderr, "Bad directory format %s: unknown filter \
type %c: %s", vfs_dirname, f_type, line);
flfree(cur_fil); cur_fil = NULL;
break;
}
cur_fil->link->linktype = f_type;
cur_fil->link->hosttype = stcopyr(f_htype,cur_fil->link->hosttype);
cur_fil->link->host = stcopy(f_host);
stfree(cur_fil->link->hsonametype); /* Should punt if same */
cur_fil->link->hsonametype = stcopy(f_ntype);
cur_fil->link->hsoname = stcopy(f_fname);
cur_fil->link->version = f_vers;
cur_fil->link->f_magic_no = f_mno;
if(tmp == 8) cur_fil->args = tokenize(f_args);
fl_insert(cur_fil,cur_link);
}
else {
fprintf(stderr,"Bad directory format %s: %s",
vfs_dirname,line,0);
flfree(cur_fil); cur_fil = NULL;
}
} /* Case 'F': */
break;
default: {
fprintf(stderr,"Bad directory format %s: %s", vfs_dirname,line,0);
}
} /* switch */
} /* while */
return retval;
}