123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163 |
- /* Sparsify.c
- J.H. Davenport 21.5.89
- usage: "sparsify filename"
- The file-name had better not be a symbolic link,
- but this isn't checked for.
- Modification: JHD 25.7.89: set owner (where possible)
- modification times, permission status etc.
- Modification: JHD 16.10.89: fix a SUNos 4 feature for files whose
- last block is precisely null
- */
- #define BSIZE 8192
- #ifdef hpux
- #include <fcntl.h>
- /* This will give us O_RDONLY and friends on HPUX */
- #include <utime.h>
- struct utimbuf hpux_utime;
- #endif
- #include <sys/file.h>
- #include <sys/types.h>
- #include <sys/stat.h>
- long lseek();
- char *malloc();
- /* Really should look it up: could be something different, but it
- doesn't really matter */
- int buf[BSIZE/4]; /* So can use word operations */
- main(argc,argv)
- int argc;
- char **argv;
- { int ifile,ofile,ilen,ans,seeking;
- long lans;
- char *oname;
- struct stat statbuf;
- if (argc != 2)
- { printf("Usage: sparsify filename\n");
- exit(-1);
- }
- ifile=open(argv[1],O_RDONLY);
- if (ifile<0)
- { perror("File couldn't be opened\n");
- exit(ifile);
- }
- oname=malloc((ilen=strlen(argv[1]))+3);
- strcpy(oname,argv[1]);
- oname[ilen]='.';
- oname[ilen+1]='z';
- oname[ilen+2]='\0';
- ofile=open(oname,O_WRONLY|O_CREAT|O_EXCL,0755);
- if (ofile<0)
- { perror("Output file couldn't be opened\n");
- exit(ifile);
- }
- seeking=0;
- while ((ilen=read(ifile,(char *)buf,BSIZE))==BSIZE)
- if (allzeros())
- { lans=lseek(ofile,(long)BSIZE,L_INCR);
- if(lans<0)
- { perror("Lseek failed\n");
- tidyup(oname);
- }
- seeking=1;
- }
- else
- { ans=write(ofile,(char *)buf,BSIZE);
- if (ans != BSIZE)
- { perror("Write failed\n");
- tidyup(oname);
- }
- seeking=0;
- }
- if (ilen > 0)
- { ans=write(ofile,(char *)buf,ilen);
- if (ans != ilen)
- { perror("Write failed\n");
- tidyup(oname);
- }
- }
- else if (seeking)
- { lans=lseek(ofile,-(long)BSIZE,L_INCR);
- if(lans<0)
- { perror("Lseek failed\n");
- tidyup(oname);
- }
- ans=write(ofile,(char *)buf,BSIZE);
- if (ans != BSIZE)
- { perror("Write failed\n");
- tidyup(oname);
- }
- }
- ilen=fstat(ifile,&statbuf);
- if (ilen < 0)
- { perror("Fstat failed\n");
- tidyup(oname);
- }
- ilen=fchmod(ofile,statbuf.st_mode);
- if (ilen < 0)
- { perror("Attempt to chmod failed\n");
- tidyup(oname);
- }
- if (geteuid())
- { if (statbuf.st_uid != geteuid())
- printf("Can't reset owner/group\n");
- }
- else {
- ilen=fchown(ofile,statbuf.st_uid,statbuf.st_gid);
- if (ilen < 0)
- { perror("Chown failed\n");
- tidyup(oname);
- }
- }
- #ifdef hpux
- /* So it's hpux */
- hpux_utime.actime=statbuf.st_atime;
- hpux_utime.modtime=statbuf.st_mtime;
- ilen=utime(oname,&hpux_utime);
- #else
- /* so it's a sun, or maybe an apollo */
- ilen=utimes(oname,&statbuf.st_atime);
- #endif
- if (ilen < 0)
- { perror("Attempt to set times failed\n");
- tidyup(oname);
- }
- ilen=unlink(argv[1]);
- if (ilen<0)
- { perror("Unlink for old file failed\n");
- printf("Tidy up by hand!\n");
- exit(-1);
- }
- ilen=link(oname,argv[1]);
- if (ilen!= 0)
- { perror("Rename failed\n");
- printf("Tidy up by hand!\n");
- exit(-1);
- }
- ilen=unlink(oname);
- if (ilen<0)
- { perror("Unlink for temporary file failed\n");
- printf("Tidy up by hand!\n");
- exit(-1);
- }
- exit(0);
- }
- tidyup(oname)
- char *oname;
- { int ilen;
- ilen=unlink(oname);
- if (ilen<0)
- { perror("Unlink for temporary file failedwhile tidying up\n");
- printf("Tidy up by hand!\n");
- exit(-1);
- }
- }
- allzeros()
- { int i;
- for(i=0;i<BSIZE/4;i++)
- if(buf[i])
- return 0;
- return 1;
- }
|