#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;
const char *f, *t;
Dir *d, nd;
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) */
strlen(t);
_nulldir(&nd);
nd.name = (char*)t;
if(_dirwstat(from, &nd) < 0){
_syserrno();
n = -1;
}
}else{
/* different directories: have to copy */
int ffd, tfd;
char buf[8192];
tfd = -1;
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;
}
|