mirror of
https://github.com/pygos/pkg-utils.git
synced 2024-12-26 06:30:52 +01:00
Add support for device special files in packages
Signed-off-by: David Oberhollenzer <goliath@infraroot.at>
This commit is contained in:
parent
6f32c6b883
commit
16bf7172fe
11 changed files with 174 additions and 14 deletions
|
@ -21,6 +21,10 @@ typedef struct image_entry_t {
|
|||
struct {
|
||||
char *target;
|
||||
} symlink;
|
||||
|
||||
struct {
|
||||
dev_t devno;
|
||||
} device;
|
||||
} data;
|
||||
} image_entry_t;
|
||||
|
||||
|
|
|
@ -53,6 +53,10 @@ typedef struct {
|
|||
uint32_t id;
|
||||
} toc_file_extra_t;
|
||||
|
||||
typedef struct {
|
||||
uint64_t devno;
|
||||
} toc_device_extra_t;
|
||||
|
||||
typedef struct {
|
||||
uint32_t id;
|
||||
/* uint8_t data[]; */
|
||||
|
|
|
@ -8,6 +8,7 @@ enum {
|
|||
UNPACK_NO_CHOWN = 0x01,
|
||||
UNPACK_NO_CHMOD = 0x02,
|
||||
UNPACK_NO_SYMLINKS = 0x04,
|
||||
UNPACK_NO_DEVICES = 0x08,
|
||||
};
|
||||
|
||||
int pkg_unpack(int rootfd, int flags, pkg_reader_t *rd);
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
#include <sys/sysmacros.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdio.h>
|
||||
|
@ -31,6 +32,18 @@ static int print_pretty(image_entry_t *ent, const char *root)
|
|||
case S_IFDIR:
|
||||
fputs("directory\n\n", stdout);
|
||||
break;
|
||||
case S_IFCHR:
|
||||
fputs("character device\n", stdout);
|
||||
printf("\tmajor: %u\n\tminor: %u\n\n",
|
||||
major(ent->data.device.devno),
|
||||
minor(ent->data.device.devno));
|
||||
break;
|
||||
case S_IFBLK:
|
||||
fputs("block device\n", stdout);
|
||||
printf("\tmajor: %u\n\tminor: %u\n\n",
|
||||
major(ent->data.device.devno),
|
||||
minor(ent->data.device.devno));
|
||||
break;
|
||||
default:
|
||||
fputs("unknown\n\n", stdout);
|
||||
goto fail_type;
|
||||
|
@ -46,12 +59,32 @@ static int print_sqfs(image_entry_t *ent, const char *root)
|
|||
mode_t mode = ent->mode & (~S_IFMT);
|
||||
(void)root;
|
||||
|
||||
if ((ent->mode & S_IFMT) == S_IFLNK)
|
||||
switch (ent->mode & S_IFMT) {
|
||||
case S_IFCHR:
|
||||
printf("%s c %o %u %u %u %u\n", ent->name, mode,
|
||||
(unsigned int)ent->uid, (unsigned int)ent->gid,
|
||||
major(ent->data.device.devno),
|
||||
minor(ent->data.device.devno));
|
||||
break;
|
||||
case S_IFBLK:
|
||||
printf("%s b %o %u %u %u %u\n", ent->name, mode,
|
||||
(unsigned int)ent->uid, (unsigned int)ent->gid,
|
||||
major(ent->data.device.devno),
|
||||
minor(ent->data.device.devno));
|
||||
break;
|
||||
case S_IFLNK:
|
||||
mode = 0777;
|
||||
/* fall-through */
|
||||
case S_IFDIR:
|
||||
case S_IFREG:
|
||||
printf("%s m %o %u %u\n", ent->name, mode,
|
||||
(unsigned int)ent->uid, (unsigned int)ent->gid);
|
||||
break;
|
||||
default:
|
||||
fputs("unknown file type in table of contents\n", stderr);
|
||||
return -1;
|
||||
}
|
||||
|
||||
printf("%s m %o %u %u\n", ent->name, mode,
|
||||
(unsigned int)ent->uid,
|
||||
(unsigned int)ent->gid);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -60,6 +93,18 @@ static int print_initrd(image_entry_t *ent, const char *root)
|
|||
mode_t mode = ent->mode & (~S_IFMT);
|
||||
|
||||
switch (ent->mode & S_IFMT) {
|
||||
case S_IFCHR:
|
||||
printf("nod /%s 0%o %u %u c %u %u\n", ent->name, mode,
|
||||
(unsigned int)ent->uid, (unsigned int)ent->gid,
|
||||
major(ent->data.device.devno),
|
||||
minor(ent->data.device.devno));
|
||||
return 0;
|
||||
case S_IFBLK:
|
||||
printf("nod /%s 0%o %u %u b %u %u\n", ent->name, mode,
|
||||
(unsigned int)ent->uid, (unsigned int)ent->gid,
|
||||
major(ent->data.device.devno),
|
||||
minor(ent->data.device.devno));
|
||||
return 0;
|
||||
case S_IFLNK:
|
||||
printf("slink /%s %s", ent->name, ent->data.symlink.target);
|
||||
mode = 0777;
|
||||
|
|
|
@ -10,10 +10,11 @@ static const struct option long_opts[] = {
|
|||
{ "list-files", no_argument, NULL, 'l' },
|
||||
{ "format", required_argument, NULL, 'F' },
|
||||
{ "no-symlinks", no_argument, NULL, 'L' },
|
||||
{ "no-devices", no_argument, NULL, 'D' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
static const char *short_opts = "r:omdR:plF:L";
|
||||
static const char *short_opts = "r:omdR:plF:LD";
|
||||
|
||||
static int unpack_packages(int repofd, int rootfd, int flags,
|
||||
struct pkg_dep_list *list)
|
||||
|
@ -154,6 +155,9 @@ static int cmd_install(int argc, char **argv)
|
|||
case 'L':
|
||||
flags |= UNPACK_NO_SYMLINKS;
|
||||
break;
|
||||
case 'D':
|
||||
flags |= UNPACK_NO_DEVICES;
|
||||
break;
|
||||
default:
|
||||
tell_read_help(argv[0]);
|
||||
goto out;
|
||||
|
|
|
@ -206,10 +206,54 @@ fail:
|
|||
return -1;
|
||||
}
|
||||
|
||||
static int filelist_mknod(input_file_t *f, void *obj)
|
||||
{
|
||||
image_entry_t **listptr = obj, *ent;
|
||||
unsigned int maj, min;
|
||||
char *ptr;
|
||||
|
||||
ent = filelist_mkentry(f, S_IFCHR);
|
||||
if (ent == NULL)
|
||||
return -1;
|
||||
|
||||
switch (f->line[0]) {
|
||||
case 'c':
|
||||
case 'C':
|
||||
break;
|
||||
case 'b':
|
||||
case 'B':
|
||||
ent->mode = (ent->mode & (~S_IFMT)) | S_IFBLK;
|
||||
break;
|
||||
default:
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (!isspace(f->line[1]))
|
||||
goto fail;
|
||||
|
||||
ptr = f->line + 1;
|
||||
while (isspace(*ptr))
|
||||
++ptr;
|
||||
|
||||
if (sscanf(ptr, "%u %u", &maj, &min) != 2)
|
||||
goto fail;
|
||||
|
||||
ent->data.device.devno = makedev(maj, min);
|
||||
|
||||
ent->next = *listptr;
|
||||
*listptr = ent;
|
||||
return 0;
|
||||
fail:
|
||||
image_entry_free(ent);
|
||||
input_file_complain(f, "error in device specification");
|
||||
return -1;
|
||||
}
|
||||
|
||||
static const keyword_handler_t line_hooks[] = {
|
||||
{ "file", filelist_mkfile },
|
||||
{ "dir", filelist_mkdir },
|
||||
{ "slink", filelist_mkslink },
|
||||
{ "nod", filelist_mknod },
|
||||
};
|
||||
|
||||
#define NUM_LINE_HOOKS (sizeof(line_hooks) / sizeof(line_hooks[0]))
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/sysmacros.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
|
|
@ -48,6 +48,16 @@ static int write_entry(pkg_writer_t *wr, image_entry_t *it)
|
|||
}
|
||||
case S_IFDIR:
|
||||
break;
|
||||
case S_IFBLK:
|
||||
case S_IFCHR: {
|
||||
toc_device_extra_t dev;
|
||||
|
||||
dev.devno = htole64(it->data.device.devno);
|
||||
|
||||
if (pkg_writer_write_payload(wr, &dev, sizeof(dev)))
|
||||
return -1;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
assert(0);
|
||||
}
|
||||
|
|
|
@ -15,10 +15,11 @@ static const struct option long_opts[] = {
|
|||
{ "no-chown", no_argument, NULL, 'o' },
|
||||
{ "no-chmod", no_argument, NULL, 'm' },
|
||||
{ "no-symlinks", no_argument, NULL, 'L' },
|
||||
{ "no-devices", no_argument, NULL, 'D' },
|
||||
{ NULL, 0, NULL, 0 },
|
||||
};
|
||||
|
||||
static const char *short_opts = "r:omL";
|
||||
static const char *short_opts = "r:omLD";
|
||||
|
||||
static int cmd_unpack(int argc, char **argv)
|
||||
{
|
||||
|
@ -38,6 +39,9 @@ static int cmd_unpack(int argc, char **argv)
|
|||
case 'L':
|
||||
flags |= UNPACK_NO_SYMLINKS;
|
||||
break;
|
||||
case 'D':
|
||||
flags |= UNPACK_NO_DEVICES;
|
||||
break;
|
||||
case 'o':
|
||||
flags |= UNPACK_NO_CHOWN;
|
||||
break;
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <stdbool.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
@ -40,6 +41,20 @@ static int create_hierarchy(int dirfd, image_entry_t *list, int flags)
|
|||
}
|
||||
}
|
||||
|
||||
for (ent = list; ent != NULL; ent = ent->next) {
|
||||
if (S_ISBLK(ent->mode) || S_ISCHR(ent->mode)) {
|
||||
if (flags & UNPACK_NO_DEVICES)
|
||||
continue;
|
||||
|
||||
if (mknodat(dirfd, ent->name, ent->mode,
|
||||
ent->data.device.devno)) {
|
||||
fprintf(stderr, "mknod %s: %s\n",
|
||||
ent->name, strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -133,13 +148,29 @@ fail_trunc:
|
|||
|
||||
static int change_permissions(int dirfd, image_entry_t *list, int flags)
|
||||
{
|
||||
while (list != NULL) {
|
||||
if (S_ISLNK(list->mode)) {
|
||||
list = list->next;
|
||||
continue;
|
||||
bool do_chmod, do_chown;
|
||||
|
||||
for (; list != NULL; list = list->next) {
|
||||
do_chmod = (flags & UNPACK_NO_CHMOD) == 0;
|
||||
do_chown = (flags & UNPACK_NO_CHOWN) == 0;
|
||||
|
||||
switch (list->mode & S_IFMT) {
|
||||
case S_IFLNK:
|
||||
if (flags & UNPACK_NO_SYMLINKS)
|
||||
continue;
|
||||
do_chmod = false;
|
||||
break;
|
||||
case S_IFBLK:
|
||||
case S_IFCHR:
|
||||
if (flags & UNPACK_NO_DEVICES)
|
||||
continue;
|
||||
do_chmod = false;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!(flags & UNPACK_NO_CHMOD) && !S_ISLNK(list->mode)) {
|
||||
if (do_chmod) {
|
||||
if (fchmodat(dirfd, list->name,
|
||||
list->mode & 07777, 0)) {
|
||||
fprintf(stderr, "%s: chmod: %s\n", list->name,
|
||||
|
@ -148,7 +179,7 @@ static int change_permissions(int dirfd, image_entry_t *list, int flags)
|
|||
}
|
||||
}
|
||||
|
||||
if (!(flags & UNPACK_NO_CHOWN)) {
|
||||
if (do_chown) {
|
||||
if (fchownat(dirfd, list->name, list->uid, list->gid,
|
||||
AT_SYMLINK_NOFOLLOW)) {
|
||||
fprintf(stderr, "%s: chown: %s\n", list->name,
|
||||
|
@ -156,8 +187,6 @@ static int change_permissions(int dirfd, image_entry_t *list, int flags)
|
|||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
list = list->next;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
|
|
@ -52,6 +52,20 @@ static int read_extra(pkg_reader_t *pkg, image_entry_t *ent)
|
|||
}
|
||||
case S_IFDIR:
|
||||
break;
|
||||
case S_IFBLK:
|
||||
case S_IFCHR: {
|
||||
toc_device_extra_t extra;
|
||||
int ret;
|
||||
|
||||
ret = pkg_reader_read_payload(pkg, &extra, sizeof(extra));
|
||||
if (ret < 0)
|
||||
return -1;
|
||||
if ((size_t)ret < sizeof(extra))
|
||||
goto fail_trunc;
|
||||
|
||||
ent->data.device.devno = le64toh(extra.devno);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
goto fail_unknown;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue