encode.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231
  1. /*
  2. ** Copyright 1998-2003 University of Illinois Board of Trustees
  3. ** Copyright 1998-2003 Mark D. Roth
  4. ** All rights reserved.
  5. **
  6. ** encode.c - libtar code to encode tar header blocks
  7. **
  8. ** Mark D. Roth <[email protected]>
  9. ** Campus Information Technologies and Educational Services
  10. ** University of Illinois at Urbana-Champaign
  11. */
  12. #include <libtarint/internal.h>
  13. #include <stdio.h>
  14. #ifndef WIN32
  15. #include <pwd.h>
  16. #include <grp.h>
  17. #endif
  18. #include <sys/types.h>
  19. #ifdef STDC_HEADERS
  20. # include <string.h>
  21. # include <stdlib.h>
  22. #endif
  23. /* magic, version, and checksum */
  24. void
  25. th_finish(TAR *t)
  26. {
  27. int i, sum = 0;
  28. if (t->options & TAR_GNU)
  29. strncpy(t->th_buf.magic, "ustar ", 8);
  30. else
  31. {
  32. strncpy(t->th_buf.version, TVERSION, TVERSLEN);
  33. strncpy(t->th_buf.magic, TMAGIC, TMAGLEN);
  34. }
  35. for (i = 0; i < T_BLOCKSIZE; i++)
  36. sum += ((char *)(&(t->th_buf)))[i];
  37. for (i = 0; i < 8; i++)
  38. sum += (' ' - t->th_buf.chksum[i]);
  39. int_to_oct(sum, t->th_buf.chksum, 8);
  40. }
  41. /* map a file mode to a typeflag */
  42. void
  43. th_set_type(TAR *t, mode_t mode)
  44. {
  45. #ifdef S_ISLNK
  46. if (S_ISLNK(mode))
  47. t->th_buf.typeflag = SYMTYPE;
  48. #endif
  49. if (S_ISREG(mode))
  50. t->th_buf.typeflag = REGTYPE;
  51. if (S_ISDIR(mode))
  52. t->th_buf.typeflag = DIRTYPE;
  53. #ifdef S_ISCHR
  54. if (S_ISCHR(mode))
  55. t->th_buf.typeflag = CHRTYPE;
  56. #endif
  57. if (S_ISBLK(mode))
  58. t->th_buf.typeflag = BLKTYPE;
  59. if (S_ISFIFO(mode)
  60. #ifdef S_ISSOCK
  61. || S_ISSOCK(mode))
  62. #else
  63. )
  64. #endif
  65. t->th_buf.typeflag = FIFOTYPE;
  66. }
  67. /* encode file path */
  68. void
  69. th_set_path(TAR *t, char *pathname)
  70. {
  71. char suffix[2] = "";
  72. char *tmp;
  73. #ifdef DEBUG
  74. printf("in th_set_path(th, pathname=\"%s\")\n", pathname);
  75. #endif
  76. if (t->th_buf.gnu_longname != NULL)
  77. free(t->th_buf.gnu_longname);
  78. t->th_buf.gnu_longname = NULL;
  79. if (pathname[strlen(pathname) - 1] != '/' && TH_ISDIR(t))
  80. strcpy(suffix, "/");
  81. if (strlen(pathname) > T_NAMELEN && (t->options & TAR_GNU))
  82. {
  83. /* GNU-style long name */
  84. t->th_buf.gnu_longname = strdup(pathname);
  85. strncpy(t->th_buf.name, t->th_buf.gnu_longname, T_NAMELEN);
  86. }
  87. else if (strlen(pathname) > T_NAMELEN)
  88. {
  89. /* POSIX-style prefix field */
  90. tmp = strchr(&(pathname[strlen(pathname) - T_NAMELEN - 1]), '/');
  91. if (tmp == NULL)
  92. {
  93. printf("!!! '/' not found in \"%s\"\n", pathname);
  94. return;
  95. }
  96. snprintf(t->th_buf.name, 100, "%s%s", &(tmp[1]), suffix);
  97. snprintf(t->th_buf.prefix,
  98. ((tmp - pathname + 1) <
  99. 155 ? (tmp - pathname + 1) : 155), "%s", pathname);
  100. }
  101. else
  102. /* classic tar format */
  103. snprintf(t->th_buf.name, 100, "%s%s", pathname, suffix);
  104. #ifdef DEBUG
  105. puts("returning from th_set_path()...");
  106. #endif
  107. }
  108. /* encode link path */
  109. void
  110. th_set_link(TAR *t, char *linkname)
  111. {
  112. #ifdef DEBUG
  113. printf("==> th_set_link(th, linkname=\"%s\")\n", linkname);
  114. #endif
  115. if (strlen(linkname) > T_NAMELEN && (t->options & TAR_GNU))
  116. {
  117. /* GNU longlink format */
  118. t->th_buf.gnu_longlink = strdup(linkname);
  119. strcpy(t->th_buf.linkname, "././@LongLink");
  120. }
  121. else
  122. {
  123. /* classic tar format */
  124. strlcpy(t->th_buf.linkname, linkname,
  125. sizeof(t->th_buf.linkname));
  126. if (t->th_buf.gnu_longlink != NULL)
  127. free(t->th_buf.gnu_longlink);
  128. t->th_buf.gnu_longlink = NULL;
  129. }
  130. }
  131. /* encode device info */
  132. void
  133. th_set_device(TAR *t, dev_t device)
  134. {
  135. #ifdef DEBUG
  136. printf("th_set_device(): major = %d, minor = %d\n",
  137. major(device), minor(device));
  138. #endif
  139. int_to_oct(major(device), t->th_buf.devmajor, 8);
  140. int_to_oct(minor(device), t->th_buf.devminor, 8);
  141. }
  142. /* encode user info */
  143. void
  144. th_set_user(TAR *t, uid_t uid)
  145. {
  146. #ifndef WIN32
  147. struct passwd *pw;
  148. pw = getpwuid(uid);
  149. if (pw != NULL)
  150. strlcpy(t->th_buf.uname, pw->pw_name, sizeof(t->th_buf.uname));
  151. #endif
  152. int_to_oct(uid, t->th_buf.uid, 8);
  153. }
  154. /* encode group info */
  155. void
  156. th_set_group(TAR *t, gid_t gid)
  157. {
  158. #ifndef WIN32
  159. struct group *gr;
  160. gr = getgrgid(gid);
  161. if (gr != NULL)
  162. strlcpy(t->th_buf.gname, gr->gr_name, sizeof(t->th_buf.gname));
  163. #endif
  164. int_to_oct(gid, t->th_buf.gid, 8);
  165. }
  166. /* encode file mode */
  167. void
  168. th_set_mode(TAR *t, mode_t fmode)
  169. {
  170. #ifndef WIN32
  171. #ifndef __BEOS__
  172. if (S_ISSOCK(fmode))
  173. {
  174. fmode &= ~S_IFSOCK;
  175. fmode |= S_IFIFO;
  176. }
  177. #endif
  178. #endif
  179. /* Looks like on windows the st_mode is longer than 8 characters. */
  180. int_to_oct(fmode & 07777777, (t)->th_buf.mode, 8);
  181. }
  182. void
  183. th_set_from_stat(TAR *t, struct stat *s)
  184. {
  185. th_set_type(t, s->st_mode);
  186. #ifndef WIN32
  187. if (S_ISCHR(s->st_mode) || S_ISBLK(s->st_mode))
  188. th_set_device(t, s->st_rdev);
  189. #endif
  190. th_set_user(t, s->st_uid);
  191. th_set_group(t, s->st_gid);
  192. th_set_mode(t, s->st_mode);
  193. th_set_mtime(t, s->st_mtime);
  194. if (S_ISREG(s->st_mode))
  195. th_set_size(t, s->st_size);
  196. else
  197. th_set_size(t, 0);
  198. }