Browse Source

Plan 9 from Bell Labs 2005-03-15

David du Colombier 19 years ago
parent
commit
58c89424a1
5 changed files with 289 additions and 5 deletions
  1. 3 1
      dist/replica/_plan9.db
  2. 3 1
      dist/replica/plan9.db
  3. 3 0
      dist/replica/plan9.log
  4. 38 3
      sys/man/1/cp
  5. 242 0
      sys/src/cmd/fcp.c

+ 3 - 1
dist/replica/_plan9.db

@@ -4697,7 +4697,7 @@ sys/man/1/cmp - 664 sys sys 944959673 1092
 sys/man/1/colors - 664 sys sys 954523212 1443
 sys/man/1/comm - 664 sys sys 944959675 665
 sys/man/1/con - 664 sys sys 1071156278 4318
-sys/man/1/cp - 664 sys sys 1015024738 1390
+sys/man/1/cp - 664 sys sys 1110816882 1947
 sys/man/1/cpp - 664 sys sys 944959674 2105
 sys/man/1/cpu - 664 sys sys 1104939775 3540
 sys/man/1/crop - 664 sys sys 984709627 2596
@@ -7553,6 +7553,7 @@ sys/src/cmd/fax/receive.c - 664 sys sys 944960990 1097
 sys/src/cmd/fax/receiverc - 775 sys sys 944960990 581
 sys/src/cmd/fax/send.c - 664 sys sys 944960990 923
 sys/src/cmd/fax/subr.c - 664 sys sys 1015090401 1245
+sys/src/cmd/fcp.c - 644 sys sys 1110816880 3780
 sys/src/cmd/file.c - 664 sys sys 1104849659 22939
 sys/src/cmd/fmt.c - 664 sys sys 1070032009 4088
 sys/src/cmd/fortune.c - 664 sys sys 1072729222 1779
@@ -12476,3 +12477,4 @@ usr/glenda/lib/profile - 664 glenda glenda 1105128663 890
 usr/glenda/readme.acme - 664 glenda glenda 1019860628 4753
 usr/glenda/readme.rio - 664 glenda glenda 1019860628 6370
 usr/glenda/tmp - 20000000775 glenda glenda 1018802620 0
+386/bin/fcp - 775 sys sys 1110859785 82162

+ 3 - 1
dist/replica/plan9.db

@@ -223,6 +223,7 @@
 386/bin/ext2srv - 775 sys sys 1108354552 173894
 386/bin/faces - 775 sys sys 1106799174 192579
 386/bin/factor - 775 sys sys 1104122008 61475
+386/bin/fcp - 775 sys sys 1110859785 82162
 386/bin/file - 775 sys sys 1108008333 112495
 386/bin/fmt - 775 sys sys 1104122009 65301
 386/bin/fortune - 775 sys sys 1104122009 67136
@@ -4697,7 +4698,7 @@ sys/man/1/cmp - 664 sys sys 944959673 1092
 sys/man/1/colors - 664 sys sys 954523212 1443
 sys/man/1/comm - 664 sys sys 944959675 665
 sys/man/1/con - 664 sys sys 1071156278 4318
-sys/man/1/cp - 664 sys sys 1015024738 1390
+sys/man/1/cp - 664 sys sys 1110816882 1947
 sys/man/1/cpp - 664 sys sys 944959674 2105
 sys/man/1/cpu - 664 sys sys 1104939775 3540
 sys/man/1/crop - 664 sys sys 984709627 2596
@@ -7553,6 +7554,7 @@ sys/src/cmd/fax/receive.c - 664 sys sys 944960990 1097
 sys/src/cmd/fax/receiverc - 775 sys sys 944960990 581
 sys/src/cmd/fax/send.c - 664 sys sys 944960990 923
 sys/src/cmd/fax/subr.c - 664 sys sys 1015090401 1245
+sys/src/cmd/fcp.c - 644 sys sys 1110816880 3780
 sys/src/cmd/file.c - 664 sys sys 1104849659 22939
 sys/src/cmd/fmt.c - 664 sys sys 1070032009 4088
 sys/src/cmd/fortune.c - 664 sys sys 1072729222 1779

+ 3 - 0
dist/replica/plan9.log

@@ -13915,3 +13915,6 @@
 1110641457 0 a sys/man/6/keys.who - 664 sys sys 1110641163 775
 1110724276 0 c rc/bin/patch/list - 775 sys sys 1110722754 716
 1110724276 1 a rc/bin/patch/save - 775 sys sys 1110722753 106
+1110817896 0 c sys/man/1/cp - 664 sys sys 1110816882 1947
+1110817896 1 a sys/src/cmd/fcp.c - 644 sys sys 1110816880 3780
+1110861106 0 a 386/bin/fcp - 775 sys sys 1110859785 82162

+ 38 - 3
sys/man/1/cp

@@ -1,6 +1,6 @@
 .TH CP 1 
 .SH NAME
-cp, mv  \- copy, move files
+cp, fcp, mv  \- copy, move files
 .SH SYNOPSIS
 .B cp
 [
@@ -14,6 +14,18 @@ cp, mv  \- copy, move files
 ]
 .I file ... directory
 .PP
+.B fcp
+[
+.B -gux
+]
+.I file1 file2
+.br
+.B fcp
+[
+.B -gux
+]
+.I file ... directory
+.PP
 .B mv
 .I file1 file2
 .br
@@ -59,6 +71,25 @@ sets the group id; and
 .B -u
 sets the group id and user id (which is usually only possible if the file server is in an administrative mode).
 .PP
+.I Fcp
+behaves like
+.I cp
+but transfers multiple blocks in parallel while copying;
+it is noticeably faster than
+.I cp
+when the files involved are stored on servers connected over long-distance lines.
+It is only appropriate to use
+.I fcp
+with file servers that respect the
+.I offset
+in
+.IR read (5)
+and
+.I write
+messages.
+This includes the disk-based file systems and ramfs
+but excludes most device file systems.
+.PP
 .I Mv
 moves
 .I file1
@@ -81,12 +112,16 @@ but it refuses to move a directory into another directory.
 .SH SOURCE
 .B /sys/src/cmd/cp.c
 .br
+.B /sys/src/cmd/fcp.c
+.br
 .B /sys/src/cmd/mv.c
 .SH "SEE ALSO"
 .IR cat (1),
-.IR stat (2)
+.IR stat (2),
+.IR read (5)
 .SH DIAGNOSTICS
-.I Cp
+.IR Cp ,
+.IR fcp ,
 and
 .I mv
 refuse to copy or move files onto themselves.

+ 242 - 0
sys/src/cmd/fcp.c

@@ -0,0 +1,242 @@
+#include <u.h>
+#include <libc.h>
+#define	DEFB	(8*1024)
+#define	Nwork	16
+
+int	failed;
+int	gflag;
+int	uflag;
+int	xflag;
+void	copy(char *from, char *to, int todir);
+int	copy1(int fdf, int fdt, char *from, char *to);
+void	worker(int fdf, int fdt, char *from, char *to);
+vlong	nextoff(void);
+void	failure(void *, char *note);
+
+QLock	lk;
+vlong	off;
+
+void
+main(int argc, char *argv[])
+{
+	Dir *dirb;
+	int todir, i;
+
+	ARGBEGIN {
+	case 'g':
+		gflag++;
+		break;
+	case 'u':
+		uflag++;
+		gflag++;
+		break;
+	case 'x':
+		xflag++;
+		break;
+	default:
+		goto usage;
+	} ARGEND
+
+	todir=0;
+	if(argc < 2)
+		goto usage;
+	dirb = dirstat(argv[argc-1]);
+	if(dirb!=nil && (dirb->mode&DMDIR))
+		todir=1;
+	if(argc>2 && !todir){
+		fprint(2, "cp: %s not a directory\n", argv[argc-1]);
+		exits("bad usage");
+	}
+	for(i=0; i<argc-1; i++)
+		copy(argv[i], argv[argc-1], todir);
+	if(failed)
+		exits("errors");
+	exits(0);
+
+usage:
+	fprint(2, "usage:\tfcp [-gux] fromfile tofile\n");
+	fprint(2, "\tfcp [-x] fromfile ... todir\n");
+	exits("usage");
+}
+
+int
+samefile(Dir *a, char *an, char *bn)
+{
+	Dir *b;
+	int ret;
+
+	ret = 0;
+	b=dirstat(bn);
+	if(b != nil)
+	if(b->qid.type==a->qid.type)
+	if(b->qid.path==a->qid.path)
+	if(b->qid.vers==a->qid.vers)
+	if(b->dev==a->dev)
+	if(b->type==a->type){
+		fprint(2, "cp: %s and %s are the same file\n", an, bn);
+		ret = 1;
+	}
+	free(b);
+	return ret;
+}
+
+void
+copy(char *from, char *to, int todir)
+{
+	Dir *dirb, dirt;
+	char name[256];
+	int fdf, fdt, mode;
+
+	if(todir){
+		char *s, *elem;
+		elem=s=from;
+		while(*s++)
+			if(s[-1]=='/')
+				elem=s;
+		sprint(name, "%s/%s", to, elem);
+		to=name;
+	}
+
+	if((dirb=dirstat(from))==nil){
+		fprint(2,"cp: can't stat %s: %r\n", from);
+		failed = 1;
+		return;
+	}
+	mode = dirb->mode;
+	if(mode&DMDIR){
+		fprint(2, "cp: %s is a directory\n", from);
+		free(dirb);
+		failed = 1;
+		return;
+	}
+	if(samefile(dirb, from, to)){
+		free(dirb);
+		failed = 1;
+		return;
+	}
+	mode &= 0777;
+	fdf=open(from, OREAD);
+	if(fdf<0){
+		fprint(2, "cp: can't open %s: %r\n", from);
+		free(dirb);
+		failed = 1;
+		return;
+	}
+	fdt=create(to, OWRITE, mode);
+	if(fdt<0){
+		fprint(2, "cp: can't create %s: %r\n", to);
+		close(fdf);
+		free(dirb);
+		failed = 1;
+		return;
+	}
+	if(copy1(fdf, fdt, from, to)==0 && (xflag || gflag || uflag)){
+		nulldir(&dirt);
+		if(xflag){
+			dirt.mtime = dirb->mtime;
+			dirt.mode = dirb->mode;
+		}
+		if(uflag)
+			dirt.uid = dirb->uid;
+		if(gflag)
+			dirt.gid = dirb->gid;
+		if(dirfwstat(fdt, &dirt) < 0)
+			fprint(2, "cp: warning: can't wstat %s: %r\n", to);
+	}			
+	free(dirb);
+	close(fdf);
+	close(fdt);
+}
+
+int
+copy1(int fdf, int fdt, char *from, char *to)
+{
+	int i, n, rv, pid[Nwork];
+	Waitmsg *w;
+
+	n = 0;
+	off = 0;
+	for(i=0; i<Nwork; i++){
+		switch(pid[n] = rfork(RFPROC|RFMEM)){
+		case 0:
+			notify(failure);
+			worker(fdf, fdt, from, to);
+		case -1:
+			break;
+		default:
+			n++;
+			break;
+		}
+	}
+	if(n == 0){
+		fprint(2, "cp: rfork: %r\n");
+		failed = 1;
+		return -1;
+	}
+
+	rv = 0;
+	while((w = wait()) != nil){
+		if(w->msg[0]){
+			rv = -1;
+			failed = 1;
+			for(i=0; i<n; i++)
+				if(pid[i] > 0)
+					postnote(PNPROC, pid[i], "failure");
+		}
+		free(w);
+	}
+	return rv;
+}
+
+void
+worker(int fdf, int fdt, char *from, char *to)
+{
+	char buf[DEFB], *bp;
+	long len, n;
+	vlong o;
+
+	len = sizeof(buf);
+	bp = buf;
+	o = nextoff();
+
+	while(n = pread(fdf, bp, len, o)){
+		if(n < 0){
+			fprint(2, "reading %s: %r\n", from);
+			_exits("bad");
+		}
+		if(pwrite(fdt, buf, n, o) != n){
+			fprint(2, "writing %s: %r\n", to);
+			_exits("bad");
+		}
+		bp += n;
+		o += n;
+		len -= n;
+		if(len == 0){
+			len = sizeof buf;
+			bp = buf;
+			o = nextoff();
+		}
+	}
+	_exits(nil);
+}
+
+vlong
+nextoff(void)
+{
+	vlong o;
+
+	qlock(&lk);
+	o = off;
+	off += DEFB;
+	qunlock(&lk);
+
+	return o;
+}
+
+void
+failure(void*, char *note)
+{
+	if(strcmp(note, "failure") == 0)
+		_exits(nil);
+	noted(NDFLT);
+}