/* splice.c by Michael Thorpe 2009-02-02 */ /* We could replace a few lines with ftruncate if it always extended */ #include #include #include #include #include "splice.h" #define BUFLEN 8192 static size_t readall(int fd,void *buf,size_t count) { size_t i; while(count) { i=read(fd,buf,count); if(i==-1) { if(errno==EAGAIN) continue; break; } if(i==0) break; buf=i+(char *)buf; count-=i; } return(count); } static size_t writeall(int fd,void *buf,size_t count) { size_t i; while(count) { i=write(fd,buf,count); if(i==-1) { if(errno==EAGAIN) continue; break; } if(i==0) break; buf=(char *)buf+i; count-=i; } return(count); } int splice(int f,off_t pos,void *old,size_t oldlen,void *new,size_t newlen) { void *buf; size_t l,m,r,w; int retval=1; if(!oldlen && !newlen) return(0); if(old && oldlen) { if(-1==lseek(f,pos,SEEK_SET)) return(1); if(readall(f,old,oldlen)) return(1); } if(!new) return(0); if(oldlen==newlen) { if(-1==lseek(f,pos,SEEK_SET)) return(1); m=writeall(f,new,newlen); return(m?m==newlen?1:-1:0); } buf=malloc(BUFLEN); if(!buf) return(1); if(oldlenpos) { l=r-poslseek(f,pos,SEEK_SET)) goto fail; m=writeall(f,buf,r); if(m != r) retval=-1; if(m) goto fail; pos+=r; if(-1==lseek(f,pos+oldlen,SEEK_SET)) goto fail; } retval=-1; if(-1==ftruncate(f,pos)) goto fail; } retval=0; fail: free(buf); return(retval); }