123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304 |
- /* $MirOS: contrib/hosted/fwcf/ft_creat.c,v 1.2 2006/09/23 23:21:04 tg Exp $ */
- /*-
- * Copyright (c) 2006
- * Thorsten Glaser <tg@mirbsd.de>
- *
- * Licensee is hereby permitted to deal in this work without restric-
- * tion, including unlimited rights to use, publicly perform, modify,
- * merge, distribute, sell, give away or sublicence, provided all co-
- * pyright notices above, these terms and the disclaimer are retained
- * in all redistributions or reproduced in accompanying documentation
- * or other materials provided with binary redistributions.
- *
- * Licensor offers the work "AS IS" and WITHOUT WARRANTY of any kind,
- * express, or implied, to the maximum extent permitted by applicable
- * law, without malicious intent or gross negligence; in no event may
- * licensor, an author or contributor be held liable for any indirect
- * or other damage, or direct damage except proven a consequence of a
- * direct error of said person and intended use of this work, loss or
- * other issues arising in any way out of its use, even if advised of
- * the possibility of such damage or existence of a defect.
- */
- #include <sys/param.h>
- #include <sys/time.h>
- #include <sys/stat.h>
- #include <err.h>
- #include <errno.h>
- #include <fcntl.h>
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <unistd.h>
- #include "defs.h"
- #include "pack.h"
- __RCSID("$MirOS: contrib/hosted/fwcf/ft_creat.c,v 1.2 2006/09/23 23:21:04 tg Exp $");
- static size_t ft_creat(char *);
- static void make_directory(char *, uint32_t, uint32_t, uint32_t, time_t);
- static void make_file(char *, uint8_t *, size_t);
- static void make_symlink(char *, uint8_t *, size_t);
- static void pop_directories(void);
- static void do_chown(char *, uid_t, gid_t);
- static void do_chmod(char *, mode_t);
- static void do_mtime(char *, time_t);
- static char *pfxname(const char *);
- static struct a_directory {
- struct a_directory *next;
- char *pathname;
- uid_t owner;
- gid_t group;
- mode_t perms;
- time_t mtime;
- } *directories;
- static char basename[PATH_MAX];
- static size_t basename_len;
- void
- ft_creatm(char *buf, const char *pathname)
- {
- directories = NULL;
- snprintf(basename, sizeof (basename), "%s/", pathname);
- basename_len = strlen(basename);
- while (*buf)
- buf += ft_creat(buf);
- if (directories != NULL)
- pop_directories();
- }
- static size_t
- ft_creat(char *buf)
- {
- uint8_t c, *p;
- char *fname;
- size_t i, type = 0, size = 0;
- uint32_t x_uid = 0, x_gid = 0, x_mode = 0;
- time_t x_mtime = 0;
- i = strlen(buf) + 1;
- p = (uint8_t *)buf + i;
- fname = pfxname(buf);
- while (*p)
- switch (c = *p++) {
- case 0x01:
- /* block special device */
- type = 1;
- break;
- case 0x02:
- /* character special device */
- type = 1;
- break;
- case 0x03:
- /* symbolic link */
- type = 2;
- break;
- case 0x04:
- /* hard link */
- type = 1;
- break;
- case 0x05:
- /* directory */
- type = 3;
- break;
- case 0x10:
- /* modification time */
- x_mtime = LOADD(p);
- p += 4;
- break;
- case 'g':
- case 'G':
- x_gid = (c == 'g') ? *p : LOADD(p);
- p += (c == 'g') ? 1 : 4;
- break;
- case 'i':
- case 'I':
- /* x_inode = (c == 'i') ? *p : LOADW(p); */
- p += (c == 'i') ? 1 : 2;
- break;
- case 'm':
- case 'M':
- x_mode = (c == 'm') ? LOADW(p) : LOADD(p);
- p += (c == 'm') ? 2 : 4;
- break;
- case 'u':
- case 'U':
- x_uid = (c == 'u') ? *p : LOADD(p);
- p += (c == 'u') ? 1 : 4;
- break;
- case 's':
- case 'S':
- size = (c == 's') ? *p : LOADT(p);
- p += (c == 's') ? 1 : 3;
- break;
- default:
- errx(1, "unknown attribute %02Xh", c);
- }
- /* skip over final NUL byte */
- ++p;
- switch (type) {
- case 1:
- /* no data, not implemented */
- if (size)
- fputs("WARN: size not allowed, ignoring\n", stderr);
- size = 0;
- break;
- case 2:
- /* symbolic link */
- make_symlink(fname, p, size);
- x_mtime = 0;
- x_mode = 0;
- break;
- case 3:
- /* directory */
- if (size)
- fputs("WARN: size not allowed, ignoring\n", stderr);
- size = 0;
- make_directory(fname, x_mode, x_uid, x_gid, x_mtime);
- goto notfile;
- break;
- case 0:
- /* regular file */
- make_file(fname, p, size);
- break;
- default:
- abort();
- }
- if (x_uid || x_gid)
- do_chown(fname, x_uid, x_gid);
- if (x_mode)
- do_chmod(fname, x_mode);
- if (x_mtime)
- do_mtime(fname, x_mtime);
- notfile:
- if (type != 3)
- free(fname);
- return ((p - (uint8_t *)buf) + size);
- }
- static void
- make_directory(char *n, uint32_t m, uint32_t u, uint32_t g, time_t t)
- {
- struct a_directory *newdir;
- if ((newdir = malloc(sizeof (struct a_directory))) == NULL)
- err(1, "out of memory");
- newdir->next = directories;
- directories = newdir;
- newdir->pathname = n;
- newdir->owner = u;
- newdir->group = g;
- newdir->perms = m;
- newdir->mtime = t;
- if (mkdir(n, 0700))
- if (errno != EEXIST)
- warn("mkdir %s", n);
- }
- static void
- make_file(char *n, uint8_t *buf, size_t len)
- {
- int fd;
- unlink(n);
- if ((fd = open(n, O_WRONLY | O_CREAT | O_TRUNC, 0700)) < 0) {
- warn("open %s", n);
- return;
- }
- if ((size_t)write(fd, buf, len) != len)
- warn("could not write %lu bytes", (u_long)len);
- if (close(fd))
- warn("close");
- }
- static void
- make_symlink(char *n, uint8_t *buf, size_t len)
- {
- char target[len + 1];
- memcpy(target, buf, len);
- target[len] = '\0';
- unlink(n);
- if (symlink(target, n))
- warn("symlink %s -> %s", n, target);
- }
- static void
- pop_directories(void)
- {
- struct a_directory *p;
- while ((p = directories) != NULL) {
- directories = p->next;
- if (p->pathname == NULL)
- warnx("pathname for a directory is NULL");
- else {
- do_chown(p->pathname, p->owner, p->group);
- do_chmod(p->pathname, p->perms);
- do_mtime(p->pathname, p->mtime);
- free(p->pathname);
- }
- free(p);
- }
- }
- static void
- do_chown(char *n, uid_t o, gid_t g)
- {
- if (lchown(n, o, g))
- warn("lchown %d:%d %s", (int)o, (int)g, n);
- }
- static void
- do_chmod(char *n, mode_t m)
- {
- if (chmod(n, m & 07777))
- warn("lchmod 0%o %s", m & 07777, n);
- }
- static void
- do_mtime(char *n, time_t t)
- {
- struct timeval tv[2] = { {0,0}, {0,0} };
- tv[1].tv_sec = t;
- if (utimes(n, tv))
- warn("utimes %d %s", (int)t, n);
- }
- static char *
- pfxname(const char *component)
- {
- char *foo;
- size_t len, x;
- len = basename_len + (x = strlen(component) + /* NUL */ 1);
- if ((foo = malloc(len)) == NULL)
- err(1, "out of memory");
- memcpy(foo, basename, basename_len);
- if ((component[0] == '.') && (component[1] == '\0'))
- foo[basename_len] = '\0';
- else
- memcpy(foo + basename_len, component, x);
- return (foo);
- }
|