Path: utzoo!attcan!uunet!world!bzs From: bzs@world.std.com (Barry Shein) Newsgroups: comp.unix.internals Subject: Re: How do you find the symbolic links to files. Message-ID: Date: 11 Dec 90 00:06:15 GMT References: <1990Dec5.190610.5612@dg-rtp.dg.com> <6647:Dec619:11:3690@kramden.acf.nyu.edu> <1990Dec7.192441.24778@dg-rtp.dg.com> <2469:Dec1001:13:4390@kramden.acf.nyu.edu> Sender: bzs@world.std.com (Barry Shein) Organization: The World Lines: 82 In-Reply-To: brnstnd@kramden.acf.nyu.edu's message of 10 Dec 90 01:13:43 GMT Actually, under BSD, you can write a fairly portable program to identify holes without getting intimate with the disk, tho I'm not entirely certain if there are any, um, holes in it, probably. This approace *is* "destructive" of the file (it destroys the holes) tho when you're done you can reconstruct the file with the holes put back. Obviously this won't work if you don't have room for the exapnded file (tho some shenanigans might only require you to have the size of the unexpanded file plus one block available, I dunno, would take some thought.) The basic idea goes like this: 1. Holes always read back as a block of zeros, so only blocks that appear to be filled with zeros are interesting. 2. If you rewrite a real hole with all zeros (still with me?) the number of blocks in the file will change, a stat() will indicate this. Here's a basic program (which could be improved in various ways, but illustrates the idea) which prints out which blocks in the file are holes, have fun picking holes in it (at least grant me that I said it was BSD-only)! -------------------- #include #include #include #include main(argc,argv) int argc; char **argv; { int i; int fd; char *buf; struct stat st, nst; if((fd = open("TMPTMP",O_RDWR)) < 0) { perror("open"); exit(1); } if(fstat(fd,&st) < 0) { perror("stat"); exit(1); } buf = (char *)malloc(st.st_blksize); for(i=0;;i++) { if(read(fd,buf,st.st_blksize) != st.st_blksize) exit(0); if(allzeros(buf,st.st_blksize)) { lseek(fd,-st.st_blksize,L_INCR); write(fd,buf,st.st_blksize); fstat(fd,&nst); if(nst.st_blocks > st.st_blocks) printf("block %d is a hole\n",i); st = nst; } } } allzeros(p,n) register char *p; register int n; { while(n--) if(*p++ != '\0') return(0); return(1); } -------------------- -- -Barry Shein Software Tool & Die | {xylogics,uunet}!world!bzs | bzs@world.std.com Purveyors to the Trade | Voice: 617-739-0202 | Login: 617-739-WRLD