xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/rename.c (revision 219b2ee8daee37f4aad58d63f21287faa8e4ffdc)
1 #include "lib.h"
2 #include <unistd.h>
3 #include <string.h>
4 #include <stdio.h>
5 #include <errno.h>
6 #include "sys9.h"
7 #include "dir.h"
8 
9 int
10 rename(const char *from, const char *to)
11 {
12 	int n, i;
13 	char *f, *t;
14 	Dir d;
15 	long mode;
16 	char cd[DIRLEN];
17 
18 	if(access(to, 0) >= 0){
19 		if(_REMOVE(to) < 0){
20 			_syserrno();
21 			return -1;
22 		}
23 	}
24 	if(_STAT(to, cd) >= 0){
25 		errno = EEXIST;
26 		return -1;
27 	}
28 	if(_STAT(from, cd) < 0){
29 		_syserrno();
30 		return -1;
31 	}
32 	convM2D(cd, &d);
33 	f = strrchr(from, '/');
34 	t = strrchr(to, '/');
35 	f = f? f+1 : from;
36 	t = t? t+1 : to;
37 	n = 0;
38 	if(f-from==t-to && strncmp(from, to, f-from)==0){
39 		/* from and to are in same directory (we miss some cases) */
40 		i = strlen(t);
41 		if(i > NAMELEN){
42 			errno = EINVAL;
43 			n = -1;
44 		}else{
45 			strcpy(d.name, t);
46 			convD2M(&d, cd);
47 			if(_WSTAT(from, cd) < 0){
48 				_syserrno();
49 				n = -1;
50 			}
51 		}
52 	}else{
53 		/* different directories: have to copy */
54 		int ffd, tfd;
55 		char buf[8192];
56 
57 		if((ffd = _OPEN(from, 0)) < 0 ||
58 		   (tfd = _CREATE(to, 1, d.mode)) < 0){
59 			_CLOSE(ffd);
60 			_syserrno();
61 			n = -1;
62 		}
63 		while(n>=0 && (n = _READ(ffd, buf, 8192) > 0))
64 			if(_WRITE(tfd, buf, n) != n){
65 				_syserrno();
66 				n = -1;
67 			}
68 		_CLOSE(ffd);
69 		_CLOSE(tfd);
70 		if(n>0)
71 			n = 0;
72 
73 	}
74 	return n;
75 }
76