archive.c 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  1. #include "mk.h"
  2. #include <ar.h>
  3. static void atimes(char *);
  4. static char *split(char*, char**);
  5. long
  6. atimeof(int force, char *name)
  7. {
  8. Symtab *sym;
  9. long t;
  10. char *archive, *member, buf[512];
  11. archive = split(name, &member);
  12. if(archive == 0)
  13. Exit();
  14. t = mtime(archive);
  15. sym = symlook(archive, S_AGG, 0);
  16. if(sym){
  17. if(force || t > sym->u.value){
  18. atimes(archive);
  19. sym->u.value = t;
  20. }
  21. }
  22. else{
  23. atimes(archive);
  24. /* mark the aggegate as having been done */
  25. symlook(strdup(archive), S_AGG, "")->u.value = t;
  26. }
  27. /* truncate long member name to sizeof of name field in archive header */
  28. snprint(buf, sizeof(buf), "%s(%.*s)", archive, utfnlen(member, SARNAME), member);
  29. sym = symlook(buf, S_TIME, 0);
  30. if (sym)
  31. return sym->u.value;
  32. return 0;
  33. }
  34. void
  35. atouch(char *name)
  36. {
  37. char *archive, *member;
  38. int fd, i;
  39. struct ar_hdr h;
  40. long t;
  41. archive = split(name, &member);
  42. if(archive == 0)
  43. Exit();
  44. fd = open(archive, ORDWR);
  45. if(fd < 0){
  46. fd = create(archive, OWRITE, 0666);
  47. if(fd < 0){
  48. perror(archive);
  49. Exit();
  50. }
  51. write(fd, ARMAG, SARMAG);
  52. }
  53. if(symlook(name, S_TIME, 0)){
  54. /* hoon off and change it in situ */
  55. LSEEK(fd, SARMAG, 0);
  56. while(read(fd, (char *)&h, sizeof(h)) == sizeof(h)){
  57. for(i = SARNAME-1; i > 0 && h.name[i] == ' '; i--)
  58. ;
  59. h.name[i+1]=0;
  60. if(strcmp(member, h.name) == 0){
  61. t = SARNAME-sizeof(h); /* ughgghh */
  62. LSEEK(fd, t, 1);
  63. fprint(fd, "%-12ld", time(0));
  64. break;
  65. }
  66. t = atol(h.size);
  67. if(t&01) t++;
  68. LSEEK(fd, t, 1);
  69. }
  70. }
  71. close(fd);
  72. }
  73. static void
  74. atimes(char *ar)
  75. {
  76. struct ar_hdr h;
  77. long at, t;
  78. int fd, i;
  79. char buf[BIGBLOCK];
  80. Dir *d;
  81. fd = open(ar, OREAD);
  82. if(fd < 0)
  83. return;
  84. if(read(fd, buf, SARMAG) != SARMAG){
  85. close(fd);
  86. return;
  87. }
  88. if((d = dirfstat(fd)) == nil){
  89. close(fd);
  90. return;
  91. }
  92. at = d->mtime;
  93. free(d);
  94. while(read(fd, (char *)&h, SAR_HDR) == SAR_HDR){
  95. t = atol(h.date);
  96. if(t >= at) /* new things in old archives confuses mk */
  97. t = at-1;
  98. if(t <= 0) /* as it sometimes happens; thanks ken */
  99. t = 1;
  100. for(i = sizeof(h.name)-1; i > 0 && h.name[i] == ' '; i--)
  101. ;
  102. if(h.name[i] == '/') /* system V bug */
  103. i--;
  104. h.name[i+1]=0; /* can stomp on date field */
  105. snprint(buf, sizeof buf, "%s(%s)", ar, h.name);
  106. symlook(strdup(buf), S_TIME, (void*)t)->u.value = t;
  107. t = atol(h.size);
  108. if(t&01) t++;
  109. LSEEK(fd, t, 1);
  110. }
  111. close(fd);
  112. }
  113. static int
  114. type(char *file)
  115. {
  116. int fd;
  117. char buf[SARMAG];
  118. fd = open(file, OREAD);
  119. if(fd < 0){
  120. if(symlook(file, S_BITCH, 0) == 0){
  121. Bprint(&bout, "%s doesn't exist: assuming it will be an archive\n", file);
  122. symlook(file, S_BITCH, (void *)file);
  123. }
  124. return 1;
  125. }
  126. if(read(fd, buf, SARMAG) != SARMAG){
  127. close(fd);
  128. return 0;
  129. }
  130. close(fd);
  131. return !strncmp(ARMAG, buf, SARMAG);
  132. }
  133. static char*
  134. split(char *name, char **member)
  135. {
  136. char *p, *q;
  137. p = strdup(name);
  138. q = utfrune(p, '(');
  139. if(q){
  140. *q++ = 0;
  141. if(member)
  142. *member = q;
  143. q = utfrune(q, ')');
  144. if (q)
  145. *q = 0;
  146. if(type(p))
  147. return p;
  148. free(p);
  149. fprint(2, "mk: '%s' is not an archive\n", name);
  150. }
  151. return 0;
  152. }