xref: /plan9-contrib/sys/src/ape/lib/ap/plan9/rename.c (revision d46c239f8612929b7dbade67d0d071633df3a15d)
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
11 rename(const char *from, const char *to)
12 {
13 	int n, i;
14 	char *f, *t;
15 	Dir *d;
16 	long mode;
17 
18 	if(access(to, 0) >= 0){
19 		if(_REMOVE(to) < 0){
20 			_syserrno();
21 			return -1;
22 		}
23 	}
24 	if((d = _dirstat(to)) != nil){
25 		free(d);
26 		errno = EEXIST;
27 		return -1;
28 	}
29 	if((d = _dirstat(from)) == nil){
30 		_syserrno();
31 		return -1;
32 	}
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 		d->name = t;
42 		if(_dirwstat(from, d) < 0){
43 			_syserrno();
44 			n = -1;
45 		}
46 	}else{
47 		/* different directories: have to copy */
48 		int ffd, tfd;
49 		char buf[8192];
50 
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