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