DataMuseum.dk

Presents historical artifacts from the history of:

Commodore CBM-900

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about Commodore CBM-900

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - download

⟦ac71a084e⟧ TextFile

    Length: 4325 (0x10e5)
    Types: TextFile
    Notes: UNIX file
    Names: »cp.c«

Derivation

└─⟦f27320a65⟧ Bits:30001972 Commodore 900 hard disk image with partial source code
    └─⟦f4b8d8c84⟧ UNIX V7 Filesystem
        └─ ⟦this⟧ »cmd/cp.c« 

TextFile

/*
 * Copy one file to another or
 * copy several files into a directory.
 * define SLOW for 'block at a time copying' .... (not recommended)
 */

#include <stdio.h>
#include <stat.h>
#include <errno.h>

#define	MAX(a, b)	((a) < (b) ? (b) : (a))
#define	or		||
#define	and		&&
#define	not		!
#define	TRUE		(0==0)
#define	FALSE		(not TRUE)

extern	int	errno;
struct stat	sb;

#ifndef		SLOW
char	buf[50*BUFSIZ];
#else
char	buf[BUFSIZ];
#endif
char	*target;
char	*namebuf;
char	*suffix;

main(argc, argv)
int argc;
char *argv[];
{
	register int i;
	register int n;
	register int status = 0;

	n = init(argc, argv);
	if (namebuf == NULL)
		return (cp(argv[1], target) ? 0 : 1);
	for (i = 1; i <= n; ++i)
		status |= cpdir(argv[i]);
	return (status ? 0 : 1);
}

/*
 * Copy inf to outf.
 */
cp(inf, outf)
char *inf, *outf;
{
#ifndef SLOW
	register char	*ip;
#endif
	register int	n;
	register int	i;
	register short	infd;
	register short	outfd;
	register short	mode;
	register ino_t	ino;
	register dev_t	dev;
	register size_t size;
#ifndef SLOW
	register char	*wp;
	register int	wflag;
#endif

	if (stat(inf, &sb) < 0) {
		cperr("%s: can't find", inf);
		return (FALSE);
	}
	if ((sb.st_mode & S_IFMT) == S_IFDIR) {
		cperr("%s: directory", inf);
		return (FALSE);
	}
	mode = sb.st_mode;
	size = sb.st_size;
	ino = sb.st_ino;
	dev = sb.st_dev;

	if (stat(outf, &sb) >= 0)
		if (sb.st_ino==ino && sb.st_dev==dev) {
			cperr("%s: can't copy file to itself", inf);
			return (FALSE);
		}
	if ((infd = open(inf, 0)) < 0) {
		cperr("%s: can't open", inf);
		return (FALSE);
	}
	if ((outfd = creat(outf, mode&0777)) < 0) {
	   if (errno == ETXTBSY)
	      cperr("%s: can't copy over busy shared text file", outf);
	   else
	      cperr("%s: can't create", outf);
	   close(infd);
	   return (FALSE);
	}

#ifndef SLOW
	while ((n = read(infd, buf, sizeof(buf))) > 0) {
#else
	while ((n = read(infd, buf, BUFSIZ)) > 0) {
#endif
		/*
		 * Check for blocks of zeroes (holes in a sparse file).
		 * However, a block of zeroes at the end of a file must be
		 * written so the file has correct length.
		 */
#ifndef		SLOW
		wp = ip = buf;
		size -= n;
		while ((n-BUFSIZ) > 0 || ((n-BUFSIZ) == 0 && size != 0)) {
			n -= BUFSIZ;
			wflag = FALSE;
			ip = wp;
			for (i = 0; i < BUFSIZ; ++i)
				if (*ip++ != '\0') {
					wflag = TRUE;
					break;
				}
			if (wflag) {
				if (write(outfd, wp, BUFSIZ) < BUFSIZ) {
					cperr("write error on %s", outf);
					close(infd);
					close(outfd);
					return (FALSE);
				}
			} else {
				lseek(outfd, (long)BUFSIZ, 1);
			}
			wp += BUFSIZ;
		}
		if (write(outfd, wp, n) < n) {
			cperr("write error on %s", outf);
			close(infd);
			close(outfd);
			return (FALSE);
		}
#else
		if ((size -= n) == (size_t)0)
			goto WRITE;
		for (i = 0; i < n; ++i)
			if (buf[i] != '\0')
				goto WRITE;
		lseek(outfd, (long)BUFSIZ, 1);
		continue;

		WRITE:
		if (write(outfd, buf, n) < n) {
			cperr("%s: write error", outf);
			close(infd);
			close(outfd);
			return (FALSE);
		}
#endif
	}

	close(infd);
	close(outfd);
	if (n < 0) {
		cperr("%s: read error", inf);
		return (FALSE);
	}
	return (TRUE);
}

/*
 * The second form of cp, copy a file into a directory. This builds the name
 * of the target file in namebuf and then just calls `cp'.
 */
cpdir(file)
char *file;
{
	register char *a, *b;

	for (a = b = file; *b != '\0'; )
		if (*b++ == '/')
			a = b;
	strcpy(suffix, a);
	return (cp(file, namebuf));
}

usage()
{
	fprintf(stderr,
	   "Usage: cp file1 file2\n       cp file ... directory\n");
	exit (2);
}

cperr(arg0)
{
	fprintf(stderr, "cp: ");
	fprintf(stderr, "%r\n", &arg0);
}

/*
 * Check whether target is a directory, regular file, non-extant or in error.
 * If a directory, malloc namebuf big enough for all names.
 * Also, set flags used by cperr.
 */
init(ac, av)
register int ac;
register char *av[];
{
	register int n;

	if (ac < 3)
		usage();
	target = av[ac-1];
	if (stat(target, &sb) == 0  and  (sb.st_mode & S_IFMT) == S_IFDIR) {
		av[ac-1] = NULL;
		n = 0;
		while (*++av != NULL)
			if (n < strlen(*av))
				n = strlen(*av);
		namebuf = malloc(n + strlen(target) + 2);
		if (namebuf == NULL) {
			cperr("out of memory");
			exit(1);
		} 
		strcpy(namebuf, target);
		suffix = namebuf + strlen(target);
		*suffix++ = '/';
		return (ac - 2);
	}
	if (ac != 3)
		usage();
	return (1);
}