sparsify.c 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. /* Sparsify.c
  2. J.H. Davenport 21.5.89
  3. usage: "sparsify filename"
  4. The file-name had better not be a symbolic link,
  5. but this isn't checked for.
  6. Modification: JHD 25.7.89: set owner (where possible)
  7. modification times, permission status etc.
  8. Modification: JHD 16.10.89: fix a SUNos 4 feature for files whose
  9. last block is precisely null
  10. */
  11. #define BSIZE 8192
  12. #ifdef hpux
  13. #include <fcntl.h>
  14. /* This will give us O_RDONLY and friends on HPUX */
  15. #include <utime.h>
  16. struct utimbuf hpux_utime;
  17. #endif
  18. #include <sys/file.h>
  19. #include <sys/types.h>
  20. #include <sys/stat.h>
  21. long lseek();
  22. char *malloc();
  23. /* Really should look it up: could be something different, but it
  24. doesn't really matter */
  25. int buf[BSIZE/4]; /* So can use word operations */
  26. main(argc,argv)
  27. int argc;
  28. char **argv;
  29. { int ifile,ofile,ilen,ans,seeking;
  30. long lans;
  31. char *oname;
  32. struct stat statbuf;
  33. if (argc != 2)
  34. { printf("Usage: sparsify filename\n");
  35. exit(-1);
  36. }
  37. ifile=open(argv[1],O_RDONLY);
  38. if (ifile<0)
  39. { perror("File couldn't be opened\n");
  40. exit(ifile);
  41. }
  42. oname=malloc((ilen=strlen(argv[1]))+3);
  43. strcpy(oname,argv[1]);
  44. oname[ilen]='.';
  45. oname[ilen+1]='z';
  46. oname[ilen+2]='\0';
  47. ofile=open(oname,O_WRONLY|O_CREAT|O_EXCL,0755);
  48. if (ofile<0)
  49. { perror("Output file couldn't be opened\n");
  50. exit(ifile);
  51. }
  52. seeking=0;
  53. while ((ilen=read(ifile,(char *)buf,BSIZE))==BSIZE)
  54. if (allzeros())
  55. { lans=lseek(ofile,(long)BSIZE,L_INCR);
  56. if(lans<0)
  57. { perror("Lseek failed\n");
  58. tidyup(oname);
  59. }
  60. seeking=1;
  61. }
  62. else
  63. { ans=write(ofile,(char *)buf,BSIZE);
  64. if (ans != BSIZE)
  65. { perror("Write failed\n");
  66. tidyup(oname);
  67. }
  68. seeking=0;
  69. }
  70. if (ilen > 0)
  71. { ans=write(ofile,(char *)buf,ilen);
  72. if (ans != ilen)
  73. { perror("Write failed\n");
  74. tidyup(oname);
  75. }
  76. }
  77. else if (seeking)
  78. { lans=lseek(ofile,-(long)BSIZE,L_INCR);
  79. if(lans<0)
  80. { perror("Lseek failed\n");
  81. tidyup(oname);
  82. }
  83. ans=write(ofile,(char *)buf,BSIZE);
  84. if (ans != BSIZE)
  85. { perror("Write failed\n");
  86. tidyup(oname);
  87. }
  88. }
  89. ilen=fstat(ifile,&statbuf);
  90. if (ilen < 0)
  91. { perror("Fstat failed\n");
  92. tidyup(oname);
  93. }
  94. ilen=fchmod(ofile,statbuf.st_mode);
  95. if (ilen < 0)
  96. { perror("Attempt to chmod failed\n");
  97. tidyup(oname);
  98. }
  99. if (geteuid())
  100. { if (statbuf.st_uid != geteuid())
  101. printf("Can't reset owner/group\n");
  102. }
  103. else {
  104. ilen=fchown(ofile,statbuf.st_uid,statbuf.st_gid);
  105. if (ilen < 0)
  106. { perror("Chown failed\n");
  107. tidyup(oname);
  108. }
  109. }
  110. #ifdef hpux
  111. /* So it's hpux */
  112. hpux_utime.actime=statbuf.st_atime;
  113. hpux_utime.modtime=statbuf.st_mtime;
  114. ilen=utime(oname,&hpux_utime);
  115. #else
  116. /* so it's a sun, or maybe an apollo */
  117. ilen=utimes(oname,&statbuf.st_atime);
  118. #endif
  119. if (ilen < 0)
  120. { perror("Attempt to set times failed\n");
  121. tidyup(oname);
  122. }
  123. ilen=unlink(argv[1]);
  124. if (ilen<0)
  125. { perror("Unlink for old file failed\n");
  126. printf("Tidy up by hand!\n");
  127. exit(-1);
  128. }
  129. ilen=link(oname,argv[1]);
  130. if (ilen!= 0)
  131. { perror("Rename failed\n");
  132. printf("Tidy up by hand!\n");
  133. exit(-1);
  134. }
  135. ilen=unlink(oname);
  136. if (ilen<0)
  137. { perror("Unlink for temporary file failed\n");
  138. printf("Tidy up by hand!\n");
  139. exit(-1);
  140. }
  141. exit(0);
  142. }
  143. tidyup(oname)
  144. char *oname;
  145. { int ilen;
  146. ilen=unlink(oname);
  147. if (ilen<0)
  148. { perror("Unlink for temporary file failedwhile tidying up\n");
  149. printf("Tidy up by hand!\n");
  150. exit(-1);
  151. }
  152. }
  153. allzeros()
  154. { int i;
  155. for(i=0;i<BSIZE/4;i++)
  156. if(buf[i])
  157. return 0;
  158. return 1;
  159. }