ft_creat.c 6.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304
  1. /* $MirOS: contrib/hosted/fwcf/ft_creat.c,v 1.2 2006/09/23 23:21:04 tg Exp $ */
  2. /*-
  3. * Copyright (c) 2006
  4. * Thorsten Glaser <tg@mirbsd.de>
  5. *
  6. * Licensee is hereby permitted to deal in this work without restric-
  7. * tion, including unlimited rights to use, publicly perform, modify,
  8. * merge, distribute, sell, give away or sublicence, provided all co-
  9. * pyright notices above, these terms and the disclaimer are retained
  10. * in all redistributions or reproduced in accompanying documentation
  11. * or other materials provided with binary redistributions.
  12. *
  13. * Licensor offers the work "AS IS" and WITHOUT WARRANTY of any kind,
  14. * express, or implied, to the maximum extent permitted by applicable
  15. * law, without malicious intent or gross negligence; in no event may
  16. * licensor, an author or contributor be held liable for any indirect
  17. * or other damage, or direct damage except proven a consequence of a
  18. * direct error of said person and intended use of this work, loss or
  19. * other issues arising in any way out of its use, even if advised of
  20. * the possibility of such damage or existence of a defect.
  21. */
  22. #include <sys/param.h>
  23. #include <sys/time.h>
  24. #include <sys/stat.h>
  25. #include <err.h>
  26. #include <errno.h>
  27. #include <fcntl.h>
  28. #include <stdio.h>
  29. #include <stdlib.h>
  30. #include <string.h>
  31. #include <unistd.h>
  32. #include "defs.h"
  33. #include "pack.h"
  34. __RCSID("$MirOS: contrib/hosted/fwcf/ft_creat.c,v 1.2 2006/09/23 23:21:04 tg Exp $");
  35. static size_t ft_creat(char *);
  36. static void make_directory(char *, uint32_t, uint32_t, uint32_t, time_t);
  37. static void make_file(char *, uint8_t *, size_t);
  38. static void make_symlink(char *, uint8_t *, size_t);
  39. static void pop_directories(void);
  40. static void do_chown(char *, uid_t, gid_t);
  41. static void do_chmod(char *, mode_t);
  42. static void do_mtime(char *, time_t);
  43. static char *pfxname(const char *);
  44. static struct a_directory {
  45. struct a_directory *next;
  46. char *pathname;
  47. uid_t owner;
  48. gid_t group;
  49. mode_t perms;
  50. time_t mtime;
  51. } *directories;
  52. static char basename[PATH_MAX];
  53. static size_t basename_len;
  54. void
  55. ft_creatm(char *buf, const char *pathname)
  56. {
  57. directories = NULL;
  58. snprintf(basename, sizeof (basename), "%s/", pathname);
  59. basename_len = strlen(basename);
  60. while (*buf)
  61. buf += ft_creat(buf);
  62. if (directories != NULL)
  63. pop_directories();
  64. }
  65. static size_t
  66. ft_creat(char *buf)
  67. {
  68. uint8_t c, *p;
  69. char *fname;
  70. size_t i, type = 0, size = 0;
  71. uint32_t x_uid = 0, x_gid = 0, x_mode = 0;
  72. time_t x_mtime = 0;
  73. i = strlen(buf) + 1;
  74. p = (uint8_t *)buf + i;
  75. fname = pfxname(buf);
  76. while (*p)
  77. switch (c = *p++) {
  78. case 0x01:
  79. /* block special device */
  80. type = 1;
  81. break;
  82. case 0x02:
  83. /* character special device */
  84. type = 1;
  85. break;
  86. case 0x03:
  87. /* symbolic link */
  88. type = 2;
  89. break;
  90. case 0x04:
  91. /* hard link */
  92. type = 1;
  93. break;
  94. case 0x05:
  95. /* directory */
  96. type = 3;
  97. break;
  98. case 0x10:
  99. /* modification time */
  100. x_mtime = LOADD(p);
  101. p += 4;
  102. break;
  103. case 'g':
  104. case 'G':
  105. x_gid = (c == 'g') ? *p : LOADD(p);
  106. p += (c == 'g') ? 1 : 4;
  107. break;
  108. case 'i':
  109. case 'I':
  110. /* x_inode = (c == 'i') ? *p : LOADW(p); */
  111. p += (c == 'i') ? 1 : 2;
  112. break;
  113. case 'm':
  114. case 'M':
  115. x_mode = (c == 'm') ? LOADW(p) : LOADD(p);
  116. p += (c == 'm') ? 2 : 4;
  117. break;
  118. case 'u':
  119. case 'U':
  120. x_uid = (c == 'u') ? *p : LOADD(p);
  121. p += (c == 'u') ? 1 : 4;
  122. break;
  123. case 's':
  124. case 'S':
  125. size = (c == 's') ? *p : LOADT(p);
  126. p += (c == 's') ? 1 : 3;
  127. break;
  128. default:
  129. errx(1, "unknown attribute %02Xh", c);
  130. }
  131. /* skip over final NUL byte */
  132. ++p;
  133. switch (type) {
  134. case 1:
  135. /* no data, not implemented */
  136. if (size)
  137. fputs("WARN: size not allowed, ignoring\n", stderr);
  138. size = 0;
  139. break;
  140. case 2:
  141. /* symbolic link */
  142. make_symlink(fname, p, size);
  143. x_mtime = 0;
  144. x_mode = 0;
  145. break;
  146. case 3:
  147. /* directory */
  148. if (size)
  149. fputs("WARN: size not allowed, ignoring\n", stderr);
  150. size = 0;
  151. make_directory(fname, x_mode, x_uid, x_gid, x_mtime);
  152. goto notfile;
  153. break;
  154. case 0:
  155. /* regular file */
  156. make_file(fname, p, size);
  157. break;
  158. default:
  159. abort();
  160. }
  161. if (x_uid || x_gid)
  162. do_chown(fname, x_uid, x_gid);
  163. if (x_mode)
  164. do_chmod(fname, x_mode);
  165. if (x_mtime)
  166. do_mtime(fname, x_mtime);
  167. notfile:
  168. if (type != 3)
  169. free(fname);
  170. return ((p - (uint8_t *)buf) + size);
  171. }
  172. static void
  173. make_directory(char *n, uint32_t m, uint32_t u, uint32_t g, time_t t)
  174. {
  175. struct a_directory *newdir;
  176. if ((newdir = malloc(sizeof (struct a_directory))) == NULL)
  177. err(1, "out of memory");
  178. newdir->next = directories;
  179. directories = newdir;
  180. newdir->pathname = n;
  181. newdir->owner = u;
  182. newdir->group = g;
  183. newdir->perms = m;
  184. newdir->mtime = t;
  185. if (mkdir(n, 0700))
  186. if (errno != EEXIST)
  187. warn("mkdir %s", n);
  188. }
  189. static void
  190. make_file(char *n, uint8_t *buf, size_t len)
  191. {
  192. int fd;
  193. unlink(n);
  194. if ((fd = open(n, O_WRONLY | O_CREAT | O_TRUNC, 0700)) < 0) {
  195. warn("open %s", n);
  196. return;
  197. }
  198. if ((size_t)write(fd, buf, len) != len)
  199. warn("could not write %lu bytes", (u_long)len);
  200. if (close(fd))
  201. warn("close");
  202. }
  203. static void
  204. make_symlink(char *n, uint8_t *buf, size_t len)
  205. {
  206. char target[len + 1];
  207. memcpy(target, buf, len);
  208. target[len] = '\0';
  209. unlink(n);
  210. if (symlink(target, n))
  211. warn("symlink %s -> %s", n, target);
  212. }
  213. static void
  214. pop_directories(void)
  215. {
  216. struct a_directory *p;
  217. while ((p = directories) != NULL) {
  218. directories = p->next;
  219. if (p->pathname == NULL)
  220. warnx("pathname for a directory is NULL");
  221. else {
  222. do_chown(p->pathname, p->owner, p->group);
  223. do_chmod(p->pathname, p->perms);
  224. do_mtime(p->pathname, p->mtime);
  225. free(p->pathname);
  226. }
  227. free(p);
  228. }
  229. }
  230. static void
  231. do_chown(char *n, uid_t o, gid_t g)
  232. {
  233. if (lchown(n, o, g))
  234. warn("lchown %d:%d %s", (int)o, (int)g, n);
  235. }
  236. static void
  237. do_chmod(char *n, mode_t m)
  238. {
  239. if (chmod(n, m & 07777))
  240. warn("lchmod 0%o %s", m & 07777, n);
  241. }
  242. static void
  243. do_mtime(char *n, time_t t)
  244. {
  245. struct timeval tv[2] = { {0,0}, {0,0} };
  246. tv[1].tv_sec = t;
  247. if (utimes(n, tv))
  248. warn("utimes %d %s", (int)t, n);
  249. }
  250. static char *
  251. pfxname(const char *component)
  252. {
  253. char *foo;
  254. size_t len, x;
  255. len = basename_len + (x = strlen(component) + /* NUL */ 1);
  256. if ((foo = malloc(len)) == NULL)
  257. err(1, "out of memory");
  258. memcpy(foo, basename, basename_len);
  259. if ((component[0] == '.') && (component[1] == '\0'))
  260. foo[basename_len] = '\0';
  261. else
  262. memcpy(foo + basename_len, component, x);
  263. return (foo);
  264. }