diff options
author | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
---|---|---|
committer | Taru Karttunen <taruti@taruti.net> | 2011-03-30 15:46:40 +0300 |
commit | e5888a1ffdae813d7575f5fb02275c6bb07e5199 (patch) | |
tree | d8d51eac403f07814b9e936eed0c9a79195e2450 /sys/src/ape/lib/ap/plan9/rename.c |
Import sources from 2011-03-30 iso image
Diffstat (limited to 'sys/src/ape/lib/ap/plan9/rename.c')
-rwxr-xr-x | sys/src/ape/lib/ap/plan9/rename.c | 76 |
1 files changed, 76 insertions, 0 deletions
diff --git a/sys/src/ape/lib/ap/plan9/rename.c b/sys/src/ape/lib/ap/plan9/rename.c new file mode 100755 index 000000000..dddfea328 --- /dev/null +++ b/sys/src/ape/lib/ap/plan9/rename.c @@ -0,0 +1,76 @@ +#include "lib.h" +#include <unistd.h> +#include <string.h> +#include <stdio.h> +#include <errno.h> +#include <stdlib.h> +#include "sys9.h" +#include "dir.h" + +int +rename(const char *from, const char *to) +{ + int n, i; + char *f, *t; + Dir *d, nd; + long mode; + + if(access(to, 0) >= 0){ + if(_REMOVE(to) < 0){ + _syserrno(); + return -1; + } + } + if((d = _dirstat(to)) != nil){ + free(d); + errno = EEXIST; + return -1; + } + if((d = _dirstat(from)) == nil){ + _syserrno(); + return -1; + } + f = strrchr(from, '/'); + t = strrchr(to, '/'); + f = f? f+1 : from; + t = t? t+1 : to; + n = 0; + if(f-from==t-to && strncmp(from, to, f-from)==0){ + /* from and to are in same directory (we miss some cases) */ + i = strlen(t); + _nulldir(&nd); + nd.name = t; + if(_dirwstat(from, &nd) < 0){ + _syserrno(); + n = -1; + } + }else{ + /* different directories: have to copy */ + int ffd, tfd; + char buf[8192]; + + if((ffd = _OPEN(from, 0)) < 0 || + (tfd = _CREATE(to, 1, d->mode)) < 0){ + _CLOSE(ffd); + _syserrno(); + n = -1; + } + while(n>=0 && (n = _READ(ffd, buf, 8192)) > 0) + if(_WRITE(tfd, buf, n) != n){ + _syserrno(); + n = -1; + } + _CLOSE(ffd); + _CLOSE(tfd); + if(n>0) + n = 0; + if(n == 0) { + if(_REMOVE(from) < 0){ + _syserrno(); + return -1; + } + } + } + free(d); + return n; +} |