4.4BSD/usr/src/contrib/xns/examples/archive/xnsrestore.c

Compare this file to the similar file:
Show the results in this format:

#ifndef lint
static char *rcsid = "$Header: xnsrestore.c,v 1.1 87/03/17 16:27:26 ed Exp $";
#endif lint

/*
 * Copyright (c) 1986, 1987 Xerox Corporation.
 */

/* $Log:	xnsrestore.c,v $
 * Revision 1.1  87/03/17  16:27:26  ed
 * Initial revision
 * 
 * 
 */

#include <stdio.h>
#include <sys/time.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <netns/ns.h>
#include <netns/sp.h>
#include <xnscourier/Filing4.h>
#include <xnscourier/except.h>
#include <xnscourier/CH.h>
#include <xnscourier/filetypes.h>
#define XNS_TIME_DIFFERENCE	2177452800	/* [(1970-1901) years * 365 days/year + 17 leap days */
						/* * 24 hours/day * 60 minutes/hour * 60 seconds/minute */

#define ROOT_DIRECTORY "/"

CourierConnection *connected;
Clearinghouse2_ObjectName hostobjname;
Authentication2_Verifier verifier;

/* the following 3 items make up the current session */
Filing4_Session session;	/* the current session */
Clearinghouse2_ObjectName username;
Filing4_Handle rootHandle;
char cur_dir[512]= 0;
char cur_pathname[512]= 0;
char cur_name[512]= 0;

static Filing4_ControlSequence nullControls = {0,0};

/* global data used to communicate with BDT procedures
 */
extern GetAttributeSequences(), 
	listproc(), isdirproc(), storeproc();

char *AttrToString();
Boolean AttrToBoolean();
LongCardinal AttrToLongCardinal();
Cardinal AttrToCardinal();

static (*ProcEachSeq)();
static FILE *fin= NULL;
FILE *lfile= NULL;

Boolean files_found= FALSE;
Boolean verbose= FALSE;
Boolean is_a_directory= FALSE;
char *logfile= 0;

char *ctime();
long time();
char *service;
extern int errno;

main(argc, argv)
int argc;
char *argv[];
{
	char *remotefile;
	char *localfile;
	int i;
	CourierConnection *hookup();
	int opt;
	extern int optind;
	extern char *optarg;

	static char *options= "vl:";
	static char *usage= "Usage: %s [-v] [-l log-file] local-file remote-file\n";

	if ( argc < 3 ) {
		fprintf(stderr, usage, argv[0]);
		exit(1);
	}

	while ((opt= getopt(argc, argv, options)) != EOF) 
		switch (opt) {
			case 'l' :
				logfile= optarg;
				break;

			case 'v' :
				verbose++;
				break;

			default:
				fprintf(stderr, "Invalid command option -%c\n", opt);
				exit(1);
		}

	localfile= argv[optind];
	optind++;
	if ( getserviceandfile(argv[optind], &service, &remotefile) == 0 ) {
		fprintf(stderr, "Invalid name %s\n", argv[optind]);
		exit(1);
	}
	DURING {
		if ( (connected= hookup(service)) == (CourierConnection *)0 ) {
				fprintf(stderr, "\nCan't connect to %s\n", service);
				exit(1);
		}
		login(0,0);

		deserializefile(localfile, remotefile);

	} HANDLER {
		FilingErrMsg(Exception.Code, Exception.Message);
	} END_HANDLER;

	return(0);
}

getserviceandfile(name, srvcptr, fileptr)
char *name;
char **srvcptr, **fileptr;
{
	char *sptr, *fptr;
	char *index(), *rindex();

	/*
	 * look for Xerox forms first:
	 *	[host]filename
	 */

	if ( (sptr= index(name, '[')) != 0 ) {
		if ( (fptr= index(sptr, ']')) != 0 ) {
			*fptr= '\0';
			*srvcptr= sptr + 1;
			*fileptr= fptr + 1;
			return(1);
		} else
			return(0);
	}

	/*
	 *	(host)filename
	 */

	if ( (sptr= index(name, '(')) != 0 ) {
		if ( (fptr= index(sptr, ')')) != 0 ) {
			*fptr= '\0';
			*srvcptr= sptr + 1;
			*fileptr= fptr + 1;
			return(1);
		} else
			return(0);
	}

	/*
	 * look for XNS style with trailing : delimiter
	 * (assumes no : in file name, use alternate spec instead)
	 *	object:domain:organization:filename
	 *		domain & organization are optional
	 */

	if ( (fptr= rindex(name, ':')) != 0 ) {
		*fptr= '\0';
		*srvcptr= name;
		*fileptr= fptr + 1;
		return(1);
	} else
		return(0);
}

copyhandle(dest,src)
	Filing4_Handle dest,src;
{
	if (dest == (Unspecified *) 0) {
		fprintf(stderr,"Oops.  dest is null in copyhandle\n");
		exit(1);
	}
	dest[0] = src[0];
	dest[1] = src[1];
}

getfilehandle(filename, handle)
	char *filename;
	Filing4_Handle handle;
{
	Filing4_Attribute pathattr[1];
	Filing4_AttributeSequence attrseq;
	Filing4_OpenResults openresult;
	Filing4_OpenResults openresult2;

	if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
		copyhandle(handle,rootHandle);
		return;
	}

	attrseq.length = 1;
	attrseq.sequence = pathattr;
	pathattr[0].type = Filing4_pathname;
	copyhandle(handle, Filing4_nullHandle);
#ifdef XEROXFSCOMPATIBILITY
	if ( filename[0] == '/')
		StringToAttr(filename+1, &pathattr[0]);
	else
		StringToAttr(filename, &pathattr[0]);
#else XEROXFSCOMPATIBILITY
	StringToAttr(filename, &pathattr[0]);
#endif XEROXFSCOMPATIBILITY
	alarm(0);
	openresult2 = Filing4_Open(connected, NULL, attrseq,
				  handle, nullControls,
				  session);
	copyhandle(handle, openresult2.file);
}

getdirhandle(filename, handle)
	char *filename;
	Filing4_Handle handle;
{
	Filing4_Attribute pathattr[1];
	Filing4_AttributeSequence attrseq;
	Filing4_OpenResults openresult;
	Filing4_OpenResults openresult2;
	char *rindex();
	char *slash;

	if (filename == (char *)0 || *filename == '\000' || (strcmp(filename, "/") == 0) ) {
		strcpy(cur_pathname, "/");
		strcpy(cur_name, "/");
		copyhandle(handle,rootHandle);
		return;
	} else if ( filename[0] == '/' ) {
		strcpy(cur_pathname, filename);
	} else {
		strcpy(cur_pathname, cur_dir);
		if ( strcmp(cur_pathname, "/") != 0 )
			strcat(cur_pathname, "/");
		strcat(cur_pathname, filename); 
	}

	if ( (slash= rindex(cur_pathname,'/')) == NULL )
		strcpy(cur_name, cur_pathname);
	else
		strcpy(cur_name, slash+1);

	if ( slash == cur_pathname) {
		copyhandle(handle, rootHandle);
		return;
	}

	attrseq.length = 1;
	attrseq.sequence = pathattr;
	pathattr[0].type = Filing4_pathname;
	copyhandle(handle, Filing4_nullHandle);
	*slash= '\0';		/* separate pathname from name */
#ifdef XEROXFSCOMPATIBILITY
	if ( cur_pathname[0] == '/' )
		StringToAttr(cur_pathname+1, &pathattr[0]);
	else
		StringToAttr(cur_pathname, &pathattr[0]);
#else XEROXFSCOMPATIBILITY
	StringToAttr(cur_pathname, &pathattr[0]);
#endif XEROXFSCOMPATIBILITY
	*slash= '/';		/* and put back */
	alarm(0);
	openresult2 = Filing4_Open(connected, NULL, attrseq,
				  handle, nullControls, session);
	copyhandle(handle, openresult2.file);
}

freefilehandle(handle)
	Filing4_Handle handle;
{
	if (handle[0] == Filing4_nullHandle[0] &&
	    handle[1] == Filing4_nullHandle[1])
		return;		/* don't free nullHandle */
	if (handle[0] == rootHandle[0] &&
	    handle[1] == rootHandle[1])
		return;		/* don't free root directory */
	alarm(0);
	Filing4_Close(connected, NULL, handle, session);
}

CourierConnection *
hookup(name)
	char *name;
{
	register struct ns_addr *hostaddr;
	extern struct ns_addr *getXNSaddr();
	Clearinghouse2_ObjectName defaultobjname;
	static char hnamebuf[128];
	CourierConnection *cconn;

	CH_NameDefault(&defaultobjname);
	hostobjname = CH_StringToName(name, &defaultobjname);
	if ((hostaddr = CH_LookupAddrDN( hostobjname, 0, hnamebuf, 128))) {
		/* should check here to be sure host is a file service */
		hostaddr->x_port = htons(5); /* ?? */
		cconn = CourierOpen(hostaddr);
		/* reset objname to flush wildcards */
		/* clear_Clearinghouse2_ThreePartName(&hostobjname); */
		hostobjname = CH_StringToName(hnamebuf, &defaultobjname);
	}
	return(cconn);
}


login(name,pwd)
	char *pwd;
	char *name;
{
	Filing4_Credentials credentials;
	Filing4_LogonResults logonresult;
	Filing4_AttributeSequence attrseq;
	Filing4_OpenResults openresult;


	if ( name != 0 )
		username = CH_StringToName(name,&hostobjname);

	if ( name == 0 && pwd == 0 ) {
		GetSimpleCredsAndVerifier(&username, 0, 
					&credentials, &verifier);
	} else {
		MakeSimpleCredsAndVerifier(&username,pwd,
					&credentials, &verifier);
	}
	logonresult= Filing4_Logon(connected, NULL, hostobjname,
					credentials, verifier);
	session = logonresult.session;

	attrseq.length= 0;
	attrseq.sequence= 0;
	openresult= Filing4_Open(connected, NULL, attrseq,
				 Filing4_nullHandle, nullControls,
				 session);
	copyhandle(rootHandle, openresult.file);
	strcpy(cur_dir, ROOT_DIRECTORY);
}

logout()
{
	Filing4_Logoff(connected, NULL, session);
	clear_Filing4_Session(&session);
}


deserializefile(local, remote)
	char *local;
	char *remote;
{
	FILE *fopen();
	Filing4_Handle remotehandle; /* note: an array */
	Filing4_Handle dirhandle; /* note: an array */
	Filing4_Handle listhandle; /* note: an array */
	Filing4_DeserializeResults results;
	Filing4_AttributeSequence attrseq;
	Filing4_Attribute attrvals[50];
	Filing4_AttributeTypeSequence typeseq;
	Filing4_AttributeType tsvals[10];
	Filing4_ScopeSequence scopeseq;
	Filing4_Scope scope;
	Filing4_ScopeSequence lscopeseq;
	Filing4_Scope lscope;
	int i;
	char *name, *rindex();
	long date;
	Boolean piping= FALSE;

	name= '\0';

	scopeseq.sequence= &scope; lscopeseq.sequence= &lscope;
	attrseq.sequence= attrvals;

	if ( strcmp(local, "-") == 0 ) {
		fin= stdin;
		piping= TRUE;
	} else {
		if ( (fin= fopen(local, "r")) == NULL ) {
			perror("Cannot open local file ");
			return(1);
		}
		if ( (name= rindex(local, '/')) == 0 ) {
			name= local;
		} else {
			name++;
		}
	}

	getdirhandle(remote, dirhandle);

	scopeseq.length= 1;
	scope.designator= Filing4_filter;
	scope.Filing4_filter_case.designator= Filing4_matches;
	scope.Filing4_filter_case.Filing4_matches_case.attribute.type= Filing4_name;
	StringToAttr(cur_name,&scope.Filing4_filter_case.Filing4_matches_case.attribute);

	typeseq.length = 2;  typeseq.sequence = tsvals;
	typeseq.sequence[0] = Filing4_name;
	typeseq.sequence[1] = Filing4_isDirectory;

	is_a_directory= FALSE;

	ProcEachSeq = isdirproc;
	Filing4_List(connected, GetAttributeSequences, dirhandle,
				     typeseq, scopeseq,
				     BulkData1_immediateSink, session);

	if ( files_found ) {
		if ( is_a_directory ) {
			if ( piping ) {
				fprintf(stderr, "Must specify file name when pinput is from stdin\n");
				return(1);
			}
			freefilehandle(dirhandle);
			getfilehandle(remote, dirhandle);
			strcat(cur_pathname, "/");
			strcat(cur_pathname, name);
		} else {
			name= cur_name;
		}
	} else {
		name= cur_name;
	}

	attrseq.length= 1;
	attrvals[0].type= Filing4_name;
	StringToAttr(name, &attrvals[0]);

	if ( AddExtendedDeserializeAttributes(fin, &attrseq) != -1 ) {
		fprintf(stderr, "Cannot determine extended attributes\n");
		fclose(fin);
		return(1);
	}

	if ( verbose ) {
		fprintf(stdout, "   Restoring %s\n", cur_pathname);
	}

	results= Filing4_Deserialize(connected, storeproc, dirhandle,
				 attrseq, nullControls,
				 BulkData1_immediateSink, session);

	if ( logfile ) {
		if ( (lfile= fopen(logfile, "w")) != NULL ) {
			scopeseq.length= 1;
			scope.designator= Filing4_filter;
			scope.Filing4_filter_case.designator= Filing4_matches;
			scope.Filing4_filter_case.Filing4_matches_case.attribute.type= Filing4_name;
			StringToAttr(name,&scope.Filing4_filter_case.Filing4_matches_case.attribute);
	
			typeseq.length = 2;  typeseq.sequence = tsvals;
			typeseq.sequence[0] = Filing4_pathname;
			typeseq.sequence[1] = Filing4_isDirectory;
	
			is_a_directory= FALSE;
	
			ProcEachSeq = isdirproc;
			Filing4_List(connected, GetAttributeSequences, dirhandle,
					     typeseq, scopeseq,
					     BulkData1_immediateSink, session);

			/*
			 * for a directory, we list all files...
			 * for non-directory, just list it...
			 */
			if ( is_a_directory ) {
				copyhandle(listhandle, results.file);
				lscopeseq.length= 1;
				lscope.designator= Filing4_depth;
				lscope.Filing4_depth_case= Filing4_allDescendants;
			} else {
				copyhandle(listhandle, dirhandle);
				lscopeseq.length= 1;
				lscope.designator= Filing4_filter;
				lscope.Filing4_filter_case.designator= Filing4_matches;
				lscope.Filing4_filter_case.Filing4_matches_case.attribute.type= Filing4_name;
				StringToAttr(name,&lscope.Filing4_filter_case.Filing4_matches_case.attribute);
	
			}

			typeseq.length = 4;
			typeseq.sequence[0] = Filing4_pathname;
			typeseq.sequence[1] = Filing4_type;
			typeseq.sequence[2] = Filing4_createdOn;
			typeseq.sequence[3] = Filing4_modifiedOn;

			date= time(0);
			fprintf(lfile, "\n\n\tRestore of %s\n\tPerformed on %s\n\n\n", cur_pathname, ctime(&date));
			fprintf(lfile, "\tFiles restored as follows:\n\n");
			fprintf(lfile, "    Create Date\t\t Modification Date\t    Type\t\t\t\t\t\tName\n\n");
	
			ProcEachSeq = listproc;
			Filing4_List(connected, GetAttributeSequences, listhandle,
					     typeseq, lscopeseq,
					     BulkData1_immediateSink, session);
			fclose(lfile);
		}
	}

	freefilehandle(results.file);
	freefilehandle(dirhandle);
}

listproc(attr)
	Filing4_AttributeSequence attr;
{
	int i;
	char *thisname, *typetostring();
	char createstr[30], modstr[30];
	LongCardinal thistype, createdate, moddate;
	Filing4_AttributeType t;

	files_found= TRUE;
	createdate= moddate= time(0);

	for (i = 0; i < attr.length; i++) {
		t = attr.sequence[i].type;
		if (t == Filing4_pathname) {
			thisname = AttrToString(&attr.sequence[i]);
		} else if (t == Filing4_type) {
			thistype = AttrToLongCardinal(&attr.sequence[i]);
		} else if (t == Filing4_createdOn) {
			createdate= AttrToLongCardinal(&attr.sequence[i]);
			createdate= createdate - XNS_TIME_DIFFERENCE;
			strcpy(createstr, ctime(&createdate));
			createstr[24]= '\0';
		} else if (t == Filing4_modifiedOn) {
			moddate= AttrToLongCardinal(&attr.sequence[i]);
			moddate= moddate - XNS_TIME_DIFFERENCE;
			strcpy(modstr, ctime(&moddate));
			modstr[24]= '\0';
		}
	}

	fprintf(lfile, "%s\t%s\t%-16s\t%s\n", createstr+4, modstr+4, typetostring(thistype), thisname);
	clear_String(&thisname);
}

isdirproc(attr)
	Filing4_AttributeSequence attr;
{
	int i;
	Filing4_AttributeType t;
	char *thisname;

	files_found= TRUE;

	for (i = 0; i < attr.length; i++) {
		t = attr.sequence[i].type;
		if (t == Filing4_isDirectory) {
			is_a_directory = AttrToBoolean(&attr.sequence[i]);
		} else if (t == Filing4_name) {
			thisname= AttrToString(&attr.sequence[i]);
			strcpy(cur_name, thisname);
			clear_String(&thisname);
		}
	}

}

#define MAXPACKS 20
static
GetAttributeSequences(conn)
	CourierConnection *conn;
{
	int count, i;
	Unspecified buffer[MAXWORDS*MAXPACKS], *bp, *bufend;
	Filing4_StreamOfAttributeSequence attrs;
	
	files_found= FALSE;

	bufend = buffer;
	bp = buffer+((MAXWORDS-1)*MAXPACKS);    /* end of available space */
	while ((count = BDTread(conn, (char*)bufend, 
				MAXWORDS*sizeof(Unspecified))) > 0) {
		bufend += count/sizeof(Unspecified);
		if (bufend > bp) {
			fprintf(stderr,"BDT read too big to fit\n");
			BDTabort(conn);
			/* should clear out stuff here if we knew how much */
		}
	}
	bp = buffer;
	while (bp < bufend) {
		bp += internalize_Filing4_StreamOfAttributeSequence(&attrs,bp);
		if (0 == (int) attrs.designator) {
		   for (i=0; i < attrs.nextSegment_case.segment.length; i++) {
			(*ProcEachSeq)(
				attrs.nextSegment_case.segment.sequence[i]);
		   }
		   free(attrs.nextSegment_case.segment.sequence);
		} else {
		   for (i = 0; i < attrs.lastSegment_case.length; i++) {
			(*ProcEachSeq)(
				attrs.lastSegment_case.sequence[i]);
		   }
		   free(attrs.lastSegment_case.sequence);
		   return;
		}
	}
}

storeproc(conn)
	CourierConnection *conn;
{
	int count, ocount, ch;
	char buffer[SPPMAXDATA];
	char *bp;

	errno = ocount = 0;
	clearerr(fin);

	while ( ((count= fread(buffer, sizeof(char), SPPMAXDATA, fin)) != 0)
		 && (ocount= BDTwrite (conn, buffer, count)) > 0) {
			;
	}
	if ( count < 0 ) {
		BDTabort(conn);
		perror("netout");
		exit(1);
	} else if ( ferror(fin) ) {
		BDTabort(conn);
		perror("fread");
		exit(1);
	} else {
		BDTclosewrite(conn);
	}
}