mirror of
https://github.com/pygos/pkg-utils.git
synced 2024-05-17 03:36:14 +02:00
Compare commits
47 commits
Author | SHA1 | Date | |
---|---|---|---|
David Oberhollenzer | 2ba65d6cfa | ||
David Oberhollenzer | 80f298de55 | ||
David Oberhollenzer | 4a7b1d3b3c | ||
David Oberhollenzer | a632656a60 | ||
David Oberhollenzer | ec1020ffc6 | ||
David Oberhollenzer | 6d053ff213 | ||
David Oberhollenzer | f426e4ef91 | ||
David Oberhollenzer | e08c819606 | ||
David Oberhollenzer | ba034260d4 | ||
David Oberhollenzer | ab753a402f | ||
David Oberhollenzer | f95f02f6be | ||
David Oberhollenzer | 5df2d5f730 | ||
David Oberhollenzer | ed6841ed17 | ||
David Oberhollenzer | 7a70868fcd | ||
David Oberhollenzer | 5f0ee09c83 | ||
David Oberhollenzer | 75e169d06a | ||
David Oberhollenzer | 9402492c16 | ||
David Oberhollenzer | 377596f37e | ||
David Oberhollenzer | 33997bdb9e | ||
David Oberhollenzer | 00db5541e9 | ||
David Oberhollenzer | 96d4d353d4 | ||
David Oberhollenzer | b30e912e97 | ||
David Oberhollenzer | 576491eae6 | ||
David Oberhollenzer | ac8e457c96 | ||
David Oberhollenzer | 214a5e917e | ||
David Oberhollenzer | e123eaf433 | ||
David Oberhollenzer | f80e4e8d29 | ||
David Oberhollenzer | 26b3683f7a | ||
David Oberhollenzer | 765c836c3d | ||
David Oberhollenzer | d94bd8ff17 | ||
David Oberhollenzer | cd79a4fccf | ||
David Oberhollenzer | eadeee25d9 | ||
David Oberhollenzer | 025ab1007b | ||
David Oberhollenzer | db25ddc108 | ||
David Oberhollenzer | 858779e42c | ||
David Oberhollenzer | c78dc2255f | ||
David Oberhollenzer | aa6bbf2ef4 | ||
David Oberhollenzer | 6cfd9a37bf | ||
David Oberhollenzer | 1205ca0f3b | ||
David Oberhollenzer | 63bad9786a | ||
David Oberhollenzer | 4d48e374d8 | ||
David Oberhollenzer | 52f7bdc5c8 | ||
David Oberhollenzer | b7e81c081b | ||
David Oberhollenzer | 46f340b20f | ||
David Oberhollenzer | 8a52ea6717 | ||
David Oberhollenzer | b2f1b5ef58 | ||
David Oberhollenzer | 48d74777e7 |
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -18,3 +18,4 @@ config.h
|
||||||
*.a
|
*.a
|
||||||
*~
|
*~
|
||||||
pkg
|
pkg
|
||||||
|
pkg2sqfs
|
||||||
|
|
|
@ -11,7 +11,7 @@ Building this package produces a program called `pkg` that can:
|
||||||
* dump the contents and meta data of such an archive for inspection.
|
* dump the contents and meta data of such an archive for inspection.
|
||||||
* install an archive and all its dependencies recursively, in topological
|
* install an archive and all its dependencies recursively, in topological
|
||||||
order, to a specified root directory.
|
order, to a specified root directory.
|
||||||
* generate file listings from archives in formats suitable for `mksquashfs`
|
* generate file listings from archives in formats suitable for `gensquashfs`
|
||||||
and Linux `CONFIG_INITRAMFS_SOURCE`.
|
and Linux `CONFIG_INITRAMFS_SOURCE`.
|
||||||
* work out a build order for source packages given information on what source
|
* work out a build order for source packages given information on what source
|
||||||
packages provide what binary packages and what binary packages they need in
|
packages provide what binary packages and what binary packages they need in
|
||||||
|
|
17
configure.ac
17
configure.ac
|
@ -1,5 +1,5 @@
|
||||||
AC_PREREQ([2.60])
|
AC_PREREQ([2.60])
|
||||||
AC_INIT([pkgtool], [0.2], [goliath@infraroot.at], pkgtool)
|
AC_INIT([pkgtool], [0.4.2], [goliath@infraroot.at], pkgtool)
|
||||||
AC_CONFIG_MACRO_DIR([m4])
|
AC_CONFIG_MACRO_DIR([m4])
|
||||||
AM_INIT_AUTOMAKE([foreign dist-xz subdir-objects])
|
AM_INIT_AUTOMAKE([foreign dist-xz subdir-objects])
|
||||||
AM_SILENT_RULES([yes])
|
AM_SILENT_RULES([yes])
|
||||||
|
@ -39,6 +39,21 @@ UL_WARN_ADD([-pedantic])
|
||||||
|
|
||||||
AC_SUBST([WARN_CFLAGS])
|
AC_SUBST([WARN_CFLAGS])
|
||||||
|
|
||||||
|
##### configuration options #####
|
||||||
|
|
||||||
|
AC_DEFINE([REPODIR], ["./"], [Default package repository directory])
|
||||||
|
AC_DEFINE([INSTALLROOT], ["./"], [Default package installation root])
|
||||||
|
|
||||||
|
AC_ARG_WITH([repo-dir],
|
||||||
|
[AS_HELP_STRING([--with-repo-dir],
|
||||||
|
[Set the default package repository directory])],
|
||||||
|
[AC_DEFINE_UNQUOTED([REPODIR], "$withval")])
|
||||||
|
|
||||||
|
AC_ARG_WITH([install-root],
|
||||||
|
[AS_HELP_STRING([--with-install-root],
|
||||||
|
[Set the default package installation directory])],
|
||||||
|
[AC_DEFINE_UNQUOTED([INSTALLROOT], "$withval")])
|
||||||
|
|
||||||
##### search for dependencies #####
|
##### search for dependencies #####
|
||||||
|
|
||||||
have_zlib="no"
|
have_zlib="no"
|
||||||
|
|
|
@ -105,14 +105,10 @@ table of contents contains an entry with the following common structure:
|
||||||
|
|
||||||
0 1 2 3
|
0 1 2 3
|
||||||
+-------+-------+-------+-------+
|
+-------+-------+-------+-------+
|
||||||
0 | mode |
|
0 | mode | user id |
|
||||||
+-------+-------+-------+-------+
|
+-------+-------+-------+-------+
|
||||||
1 | user id |
|
1 | group id | path length |
|
||||||
+-------+-------+-------+-------+
|
+-------+-------+-------+-------+
|
||||||
2 | group id |
|
|
||||||
+-------+-------+-------+-------+
|
|
||||||
3 | path length |
|
|
||||||
+---------------+
|
|
||||||
|
|
||||||
The mode field contains standard UNIX permissions. The user ID and group ID
|
The mode field contains standard UNIX permissions. The user ID and group ID
|
||||||
fields contain the numeric IDs of the user and group respectively that own
|
fields contain the numeric IDs of the user and group respectively that own
|
||||||
|
@ -142,8 +138,6 @@ On the bit level, the mode field is structured as follows:
|
||||||
| +------------------------- set UID bit
|
| +------------------------- set UID bit
|
||||||
+----------------------------- file type
|
+----------------------------- file type
|
||||||
|
|
||||||
The upper 16 bit of the mode filed must be set to zero.
|
|
||||||
|
|
||||||
Currently, the following file types are supported:
|
Currently, the following file types are supported:
|
||||||
|
|
||||||
* `S_IFCHR` with a value of 2. The entry defines a character device.
|
* `S_IFCHR` with a value of 2. The entry defines a character device.
|
||||||
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
|
|
||||||
#include "pkgformat.h"
|
#include "pkg/pkgformat.h"
|
||||||
|
|
||||||
typedef struct compressor_stream_t {
|
typedef struct compressor_stream_t {
|
||||||
ssize_t (*write)(struct compressor_stream_t *stream, const uint8_t *in,
|
ssize_t (*write)(struct compressor_stream_t *stream, const uint8_t *in,
|
||||||
|
@ -24,21 +24,14 @@ typedef struct compressor_t {
|
||||||
const char *name;
|
const char *name;
|
||||||
PKG_COMPRESSION id;
|
PKG_COMPRESSION id;
|
||||||
|
|
||||||
compressor_stream_t *(*compression_stream)(struct compressor_t *cmp);
|
compressor_stream_t *(*compression_stream)(struct compressor_t *cmp,
|
||||||
|
void *options);
|
||||||
|
|
||||||
compressor_stream_t *(*uncompression_stream)(struct compressor_t *cmp);
|
compressor_stream_t *(*uncompression_stream)(struct compressor_t *cmp);
|
||||||
} compressor_t;
|
} compressor_t;
|
||||||
|
|
||||||
void compressor_register(compressor_t *compressor);
|
|
||||||
|
|
||||||
compressor_t *compressor_by_name(const char *name);
|
compressor_t *compressor_by_name(const char *name);
|
||||||
|
|
||||||
compressor_t *compressor_by_id(PKG_COMPRESSION id);
|
compressor_t *compressor_by_id(PKG_COMPRESSION id);
|
||||||
|
|
||||||
#define REGISTER_COMPRESSOR(compressor) \
|
|
||||||
static void __attribute__((constructor)) register_##compressor(void) \
|
|
||||||
{ \
|
|
||||||
compressor_register((compressor_t *)&compressor); \
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif /* COMPRESSOR_H */
|
#endif /* COMPRESSOR_H */
|
|
@ -31,7 +31,6 @@ typedef struct image_entry_t {
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
TOC_FORMAT_PRETTY = 0,
|
TOC_FORMAT_PRETTY = 0,
|
||||||
TOC_FORMAT_SQFS = 1,
|
|
||||||
TOC_FORMAT_INITRD = 2,
|
TOC_FORMAT_INITRD = 2,
|
||||||
TOC_FORMAT_PKG = 3,
|
TOC_FORMAT_PKG = 3,
|
||||||
} TOC_FORMAT;
|
} TOC_FORMAT;
|
||||||
|
|
|
@ -36,10 +36,9 @@ typedef struct {
|
||||||
} record_t;
|
} record_t;
|
||||||
|
|
||||||
typedef struct {
|
typedef struct {
|
||||||
uint32_t mode;
|
uint16_t mode;
|
||||||
uint32_t uid;
|
uint16_t uid;
|
||||||
uint32_t gid;
|
uint16_t gid;
|
||||||
|
|
||||||
uint16_t path_length;
|
uint16_t path_length;
|
||||||
/* uint8_t path[]; */
|
/* uint8_t path[]; */
|
||||||
} toc_entry_t;
|
} toc_entry_t;
|
|
@ -1,6 +1,6 @@
|
||||||
/* SPDX-License-Identifier: ISC */
|
/* SPDX-License-Identifier: ISC */
|
||||||
#ifndef DEPGRAPH_H
|
#ifndef PKGLIST_H
|
||||||
#define DEPGRAPH_H
|
#define PKGLIST_H
|
||||||
|
|
||||||
struct pkg_dep_node {
|
struct pkg_dep_node {
|
||||||
char *name;
|
char *name;
|
||||||
|
@ -30,4 +30,4 @@ int collect_dependencies(int repofd, struct pkg_dep_list *list);
|
||||||
|
|
||||||
int sort_by_dependencies(struct pkg_dep_list *list);
|
int sort_by_dependencies(struct pkg_dep_list *list);
|
||||||
|
|
||||||
#endif /* DEPGRAPH_H */
|
#endif /* PKGLIST_H */
|
|
@ -4,8 +4,8 @@
|
||||||
|
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
|
|
||||||
|
#include "comp/compressor.h"
|
||||||
#include "pkgformat.h"
|
#include "pkgformat.h"
|
||||||
#include "compressor.h"
|
|
||||||
|
|
||||||
typedef struct pkg_writer_t pkg_writer_t;
|
typedef struct pkg_writer_t pkg_writer_t;
|
||||||
|
|
|
@ -9,4 +9,30 @@ libfilelist_a_SOURCES = lib/filelist/dump_toc.c lib/filelist/image_entry.c
|
||||||
libfilelist_a_SOURCES += lib/filelist/image_entry_sort.c
|
libfilelist_a_SOURCES += lib/filelist/image_entry_sort.c
|
||||||
libfilelist_a_SOURCES += include/filelist/image_entry.h
|
libfilelist_a_SOURCES += include/filelist/image_entry.h
|
||||||
|
|
||||||
noinst_LIBRARIES += libutil.a libfilelist.a
|
libcomp_a_SOURCES = lib/comp/compressor.c lib/comp/none.c
|
||||||
|
libcomp_a_SOURCES += include/comp/compressor.h lib/comp/internal.h
|
||||||
|
libcomp_a_CFLAGS = $(AM_CFLAGS)
|
||||||
|
libcomp_a_CPPFLAGS = $(AM_CPPFLAGS)
|
||||||
|
|
||||||
|
if WITH_ZLIB
|
||||||
|
libcomp_a_SOURCES += lib/comp/zlib.c
|
||||||
|
|
||||||
|
libcomp_a_CFLAGS += $(ZLIB_CFLAGS)
|
||||||
|
libcomp_a_CPPFLAGS += -DWITH_ZLIB
|
||||||
|
endif
|
||||||
|
|
||||||
|
if WITH_LZMA
|
||||||
|
libcomp_a_SOURCES += lib/comp/lzma.c
|
||||||
|
|
||||||
|
libcomp_a_CFLAGS += $(XZ_CFLAGS)
|
||||||
|
libcomp_a_CPPFLAGS += -DWITH_LZMA
|
||||||
|
endif
|
||||||
|
|
||||||
|
libpkg_a_SOURCES = include/pkg/pkgformat.h include/pkg/pkgreader.h
|
||||||
|
libpkg_a_SOURCES += include/pkg/pkgio.h include/pkg/pkgwriter.h
|
||||||
|
libpkg_a_SOURCES += include/pkg/pkglist.h
|
||||||
|
libpkg_a_SOURCES += lib/pkg/pkgreader.c lib/pkg/pkgwriter.c
|
||||||
|
libpkg_a_SOURCES += lib/pkg/pkg_unpack.c lib/pkg/pkgio_rd_image_entry.c
|
||||||
|
libpkg_a_SOURCES += lib/pkg/collect.c lib/pkg/pkglist.c lib/pkg/tsort.c
|
||||||
|
|
||||||
|
noinst_LIBRARIES += libutil.a libfilelist.a libcomp.a libpkg.a
|
||||||
|
|
39
lib/comp/compressor.c
Normal file
39
lib/comp/compressor.c
Normal file
|
@ -0,0 +1,39 @@
|
||||||
|
/* SPDX-License-Identifier: ISC */
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "internal.h"
|
||||||
|
|
||||||
|
static compressor_t *compressors[] = {
|
||||||
|
[PKG_COMPRESSION_NONE] = &comp_none,
|
||||||
|
#ifdef WITH_ZLIB
|
||||||
|
[PKG_COMPRESSION_ZLIB] = &comp_zlib,
|
||||||
|
#endif
|
||||||
|
#ifdef WITH_LZMA
|
||||||
|
[PKG_COMPRESSION_LZMA] = &comp_lzma,
|
||||||
|
#endif
|
||||||
|
};
|
||||||
|
|
||||||
|
compressor_t *compressor_by_name(const char *name)
|
||||||
|
{
|
||||||
|
size_t i;
|
||||||
|
|
||||||
|
for (i = 0; i < sizeof(compressors) / sizeof(compressors[0]); ++i) {
|
||||||
|
if (compressors[i] == NULL)
|
||||||
|
continue;
|
||||||
|
if (strcmp(compressors[i]->name, name) == 0)
|
||||||
|
return compressors[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
compressor_t *compressor_by_id(PKG_COMPRESSION id)
|
||||||
|
{
|
||||||
|
if ((int)id < 0)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
if ((size_t)id >= sizeof(compressors) / sizeof(compressors[0]))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
return compressors[id];
|
||||||
|
}
|
11
lib/comp/internal.h
Normal file
11
lib/comp/internal.h
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
/* SPDX-License-Identifier: ISC */
|
||||||
|
#ifndef INTERNAL_H
|
||||||
|
#define INTERNAL_H
|
||||||
|
|
||||||
|
#include "comp/compressor.h"
|
||||||
|
|
||||||
|
extern compressor_t comp_lzma;
|
||||||
|
extern compressor_t comp_none;
|
||||||
|
extern compressor_t comp_zlib;
|
||||||
|
|
||||||
|
#endif /* INTERNAL_H */
|
|
@ -5,7 +5,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <lzma.h>
|
#include <lzma.h>
|
||||||
|
|
||||||
#include "compressor.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#define CHUNK_SIZE 16384
|
#define CHUNK_SIZE 16384
|
||||||
|
|
||||||
|
@ -17,6 +17,7 @@ typedef struct {
|
||||||
int used;
|
int used;
|
||||||
bool eof;
|
bool eof;
|
||||||
bool error;
|
bool error;
|
||||||
|
size_t dict_size;
|
||||||
} lzma_stream_t;
|
} lzma_stream_t;
|
||||||
|
|
||||||
static ssize_t lzma_write(compressor_stream_t *base,
|
static ssize_t lzma_write(compressor_stream_t *base,
|
||||||
|
@ -100,7 +101,7 @@ static void lzma_destroy(compressor_stream_t *base)
|
||||||
free(lzma);
|
free(lzma);
|
||||||
}
|
}
|
||||||
|
|
||||||
static compressor_stream_t *create_stream(bool compress)
|
static compressor_stream_t *create_stream(bool compress, size_t dict_size)
|
||||||
{
|
{
|
||||||
lzma_stream_t *lzma = calloc(1, sizeof(*lzma));
|
lzma_stream_t *lzma = calloc(1, sizeof(*lzma));
|
||||||
compressor_stream_t *base;
|
compressor_stream_t *base;
|
||||||
|
@ -113,6 +114,7 @@ static compressor_stream_t *create_stream(bool compress)
|
||||||
}
|
}
|
||||||
|
|
||||||
lzma->action = LZMA_RUN;
|
lzma->action = LZMA_RUN;
|
||||||
|
lzma->dict_size = dict_size;
|
||||||
|
|
||||||
base = (compressor_stream_t *)lzma;
|
base = (compressor_stream_t *)lzma;
|
||||||
base->write = lzma_write;
|
base->write = lzma_write;
|
||||||
|
@ -126,6 +128,9 @@ static compressor_stream_t *create_stream(bool compress)
|
||||||
if (lzma_lzma_preset(&opt_lzma2, LZMA_PRESET_DEFAULT))
|
if (lzma_lzma_preset(&opt_lzma2, LZMA_PRESET_DEFAULT))
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
||||||
|
if (dict_size)
|
||||||
|
opt_lzma2.dict_size = dict_size;
|
||||||
|
|
||||||
filters[0].id = LZMA_FILTER_LZMA2;
|
filters[0].id = LZMA_FILTER_LZMA2;
|
||||||
filters[0].options = &opt_lzma2;
|
filters[0].options = &opt_lzma2;
|
||||||
|
|
||||||
|
@ -148,23 +153,21 @@ fail:
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static compressor_stream_t *lzma_compress(compressor_t *cmp)
|
static compressor_stream_t *lzma_compress(compressor_t *cmp, void *options)
|
||||||
{
|
{
|
||||||
(void)cmp;
|
(void)cmp;
|
||||||
return create_stream(true);
|
return create_stream(true, options == NULL ? 0 : *((size_t *)options));
|
||||||
}
|
}
|
||||||
|
|
||||||
static compressor_stream_t *lzma_uncompress(compressor_t *cmp)
|
static compressor_stream_t *lzma_uncompress(compressor_t *cmp)
|
||||||
{
|
{
|
||||||
(void)cmp;
|
(void)cmp;
|
||||||
return create_stream(false);
|
return create_stream(false, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
static compressor_t lzma = {
|
compressor_t comp_lzma = {
|
||||||
.name = "lzma",
|
.name = "lzma",
|
||||||
.id = PKG_COMPRESSION_LZMA,
|
.id = PKG_COMPRESSION_LZMA,
|
||||||
.compression_stream = lzma_compress,
|
.compression_stream = lzma_compress,
|
||||||
.uncompression_stream = lzma_uncompress,
|
.uncompression_stream = lzma_uncompress,
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_COMPRESSOR(lzma)
|
|
|
@ -4,7 +4,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "compressor.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#define CHUNK_SIZE 16384
|
#define CHUNK_SIZE 16384
|
||||||
|
|
||||||
|
@ -62,11 +62,12 @@ static void dummy_destroy(compressor_stream_t *base)
|
||||||
free(base);
|
free(base);
|
||||||
}
|
}
|
||||||
|
|
||||||
static compressor_stream_t *create_dummy_stream(compressor_t *cmp)
|
static compressor_stream_t *create_dummy_stream(compressor_t *cmp,
|
||||||
|
void *options)
|
||||||
{
|
{
|
||||||
dummy_stream_t *dummy = calloc(1, sizeof(*dummy));
|
dummy_stream_t *dummy = calloc(1, sizeof(*dummy));
|
||||||
compressor_stream_t *base;
|
compressor_stream_t *base;
|
||||||
(void)cmp;
|
(void)cmp; (void)options;
|
||||||
|
|
||||||
if (dummy == NULL) {
|
if (dummy == NULL) {
|
||||||
perror("creating dummy compressor stream");
|
perror("creating dummy compressor stream");
|
||||||
|
@ -81,11 +82,14 @@ static compressor_stream_t *create_dummy_stream(compressor_t *cmp)
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static compressor_t none = {
|
static compressor_stream_t *create_dummy_uncompressor(compressor_t *cmp)
|
||||||
|
{
|
||||||
|
return create_dummy_stream(cmp, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
compressor_t comp_none = {
|
||||||
.name = "none",
|
.name = "none",
|
||||||
.id = PKG_COMPRESSION_NONE,
|
.id = PKG_COMPRESSION_NONE,
|
||||||
.compression_stream = create_dummy_stream,
|
.compression_stream = create_dummy_stream,
|
||||||
.uncompression_stream = create_dummy_stream,
|
.uncompression_stream = create_dummy_uncompressor,
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_COMPRESSOR(none)
|
|
|
@ -5,7 +5,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <zlib.h>
|
#include <zlib.h>
|
||||||
|
|
||||||
#include "compressor.h"
|
#include "internal.h"
|
||||||
|
|
||||||
#define CHUNK_SIZE 16384
|
#define CHUNK_SIZE 16384
|
||||||
|
|
||||||
|
@ -147,9 +147,9 @@ static compressor_stream_t *create_stream(bool compress)
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
static compressor_stream_t *zlib_compress(compressor_t *cmp)
|
static compressor_stream_t *zlib_compress(compressor_t *cmp, void *options)
|
||||||
{
|
{
|
||||||
(void)cmp;
|
(void)cmp; (void)options;
|
||||||
return create_stream(true);
|
return create_stream(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -159,11 +159,9 @@ static compressor_stream_t *zlib_uncompress(compressor_t *cmp)
|
||||||
return create_stream(false);
|
return create_stream(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
static compressor_t zlib = {
|
compressor_t comp_zlib = {
|
||||||
.name = "zlib",
|
.name = "zlib",
|
||||||
.id = PKG_COMPRESSION_ZLIB,
|
.id = PKG_COMPRESSION_ZLIB,
|
||||||
.compression_stream = zlib_compress,
|
.compression_stream = zlib_compress,
|
||||||
.uncompression_stream = zlib_uncompress,
|
.uncompression_stream = zlib_uncompress,
|
||||||
};
|
};
|
||||||
|
|
||||||
REGISTER_COMPRESSOR(zlib)
|
|
|
@ -55,40 +55,6 @@ fail_type:
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int print_sqfs(image_entry_t *ent, const char *root)
|
|
||||||
{
|
|
||||||
mode_t mode = ent->mode & (~S_IFMT);
|
|
||||||
(void)root;
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int print_initrd(image_entry_t *ent, const char *root)
|
static int print_initrd(image_entry_t *ent, const char *root)
|
||||||
{
|
{
|
||||||
mode_t mode = ent->mode & (~S_IFMT);
|
mode_t mode = ent->mode & (~S_IFMT);
|
||||||
|
@ -156,7 +122,7 @@ static int print_pkg(image_entry_t *ent, const char *root)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
printf(" %s 0%o %u %u ", ent->name, mode,
|
printf(" \"%s\" 0%o %u %u ", ent->name, mode,
|
||||||
(unsigned int)ent->uid, (unsigned int)ent->gid);
|
(unsigned int)ent->uid, (unsigned int)ent->gid);
|
||||||
|
|
||||||
switch (ent->mode & S_IFMT) {
|
switch (ent->mode & S_IFMT) {
|
||||||
|
@ -186,7 +152,6 @@ static int print_pkg(image_entry_t *ent, const char *root)
|
||||||
|
|
||||||
static print_fun_t printers[] = {
|
static print_fun_t printers[] = {
|
||||||
[TOC_FORMAT_PRETTY] = print_pretty,
|
[TOC_FORMAT_PRETTY] = print_pretty,
|
||||||
[TOC_FORMAT_SQFS] = print_sqfs,
|
|
||||||
[TOC_FORMAT_INITRD] = print_initrd,
|
[TOC_FORMAT_INITRD] = print_initrd,
|
||||||
[TOC_FORMAT_PKG] = print_pkg,
|
[TOC_FORMAT_PKG] = print_pkg,
|
||||||
};
|
};
|
||||||
|
|
|
@ -6,6 +6,8 @@
|
||||||
|
|
||||||
static int compare_ent(image_entry_t *a, image_entry_t *b)
|
static int compare_ent(image_entry_t *a, image_entry_t *b)
|
||||||
{
|
{
|
||||||
|
int diff;
|
||||||
|
|
||||||
/* directories < .. < symlinks < devices < .. < files */
|
/* directories < .. < symlinks < devices < .. < files */
|
||||||
switch (a->mode & S_IFMT) {
|
switch (a->mode & S_IFMT) {
|
||||||
case S_IFDIR:
|
case S_IFDIR:
|
||||||
|
@ -31,7 +33,8 @@ static int compare_ent(image_entry_t *a, image_entry_t *b)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
out_len:
|
out_len:
|
||||||
return (int)strlen(a->name) - (int)strlen(b->name);
|
diff = (int)strlen(a->name) - (int)strlen(b->name);
|
||||||
|
return diff ? diff : strcmp(a->name, b->name);
|
||||||
out_fsize:
|
out_fsize:
|
||||||
if (a->data.file.size > b->data.file.size)
|
if (a->data.file.size > b->data.file.size)
|
||||||
return 1;
|
return 1;
|
||||||
|
@ -65,6 +68,34 @@ static image_entry_t *insert_sorted(image_entry_t *list, image_entry_t *ent)
|
||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void remove_duplicates(image_entry_t *list)
|
||||||
|
{
|
||||||
|
image_entry_t *it = list, *old;
|
||||||
|
int equal;
|
||||||
|
|
||||||
|
if (it == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
|
while (it->next != NULL) {
|
||||||
|
equal = 0;
|
||||||
|
|
||||||
|
if (S_ISDIR(it->mode) && S_ISDIR(it->next->mode)) {
|
||||||
|
equal = (strcmp(it->name, it->next->name) == 0);
|
||||||
|
equal = equal && (it->mode == it->next->mode);
|
||||||
|
equal = equal && (it->uid == it->next->uid);
|
||||||
|
equal = equal && (it->gid == it->next->gid);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (equal) {
|
||||||
|
old = it->next;
|
||||||
|
it->next = old->next;
|
||||||
|
image_entry_free(old);
|
||||||
|
} else {
|
||||||
|
it = it->next;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
image_entry_t *image_entry_sort(image_entry_t *list)
|
image_entry_t *image_entry_sort(image_entry_t *list)
|
||||||
{
|
{
|
||||||
image_entry_t *sorted = NULL, *ent;
|
image_entry_t *sorted = NULL, *ent;
|
||||||
|
@ -76,5 +107,7 @@ image_entry_t *image_entry_sort(image_entry_t *list)
|
||||||
sorted = insert_sorted(sorted, ent);
|
sorted = insert_sorted(sorted, ent);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
remove_duplicates(sorted);
|
||||||
|
|
||||||
return sorted;
|
return sorted;
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,8 +3,8 @@
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "pkgreader.h"
|
#include "pkg/pkgreader.h"
|
||||||
#include "depgraph.h"
|
#include "pkg/pkglist.h"
|
||||||
|
|
||||||
int collect_dependencies(int repofd, struct pkg_dep_list *list)
|
int collect_dependencies(int repofd, struct pkg_dep_list *list)
|
||||||
{
|
{
|
|
@ -8,7 +8,7 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "pkgio.h"
|
#include "pkg/pkgio.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
|
|
||||||
static int create_hierarchy(int dirfd, image_entry_t *list, int flags)
|
static int create_hierarchy(int dirfd, image_entry_t *list, int flags)
|
|
@ -4,7 +4,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "pkgio.h"
|
#include "pkg/pkgio.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
|
|
||||||
static int read_extra(pkg_reader_t *pkg, image_entry_t *ent)
|
static int read_extra(pkg_reader_t *pkg, image_entry_t *ent)
|
|
@ -3,7 +3,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "depgraph.h"
|
#include "pkg/pkglist.h"
|
||||||
|
|
||||||
struct pkg_dep_node *append_pkg(struct pkg_dep_list *list, const char *name)
|
struct pkg_dep_node *append_pkg(struct pkg_dep_list *list, const char *name)
|
||||||
{
|
{
|
|
@ -8,9 +8,9 @@
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
#include <ctype.h>
|
#include <ctype.h>
|
||||||
|
|
||||||
|
#include "comp/compressor.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "pkgreader.h"
|
#include "pkg/pkgreader.h"
|
||||||
#include "compressor.h"
|
|
||||||
|
|
||||||
struct pkg_reader_t {
|
struct pkg_reader_t {
|
||||||
int fd;
|
int fd;
|
||||||
|
@ -235,26 +235,29 @@ record_t *pkg_reader_current_record_header(pkg_reader_t *rd)
|
||||||
|
|
||||||
ssize_t pkg_reader_read_payload(pkg_reader_t *rd, void *out, size_t size)
|
ssize_t pkg_reader_read_payload(pkg_reader_t *rd, void *out, size_t size)
|
||||||
{
|
{
|
||||||
ssize_t ret;
|
ssize_t ret, total = 0;
|
||||||
|
|
||||||
if (rd->have_error)
|
do {
|
||||||
return -1;
|
if (rd->have_error)
|
||||||
|
return -1;
|
||||||
|
|
||||||
if (rd->have_eof || rd->offset_raw == rd->current.raw_size)
|
if (rd->have_eof || rd->offset_raw == rd->current.raw_size)
|
||||||
return 0;
|
break;
|
||||||
|
|
||||||
if (prefetch_compressed(rd))
|
if (prefetch_compressed(rd))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
if (size >= (rd->current.raw_size - rd->offset_raw))
|
ret = rd->stream->read(rd->stream, out, size);
|
||||||
rd->stream->flush(rd->stream);
|
if (ret < 0)
|
||||||
|
return -1;
|
||||||
|
|
||||||
ret = rd->stream->read(rd->stream, out, size);
|
rd->offset_raw += ret;
|
||||||
if (ret < 0)
|
out = (char *)out + ret;
|
||||||
return -1;
|
size -= ret;
|
||||||
|
total += ret;
|
||||||
|
} while (size > 0);
|
||||||
|
|
||||||
rd->offset_raw += ret;
|
return total;
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int pkg_reader_rewind(pkg_reader_t *rd)
|
int pkg_reader_rewind(pkg_reader_t *rd)
|
|
@ -6,7 +6,7 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
#include "pkgwriter.h"
|
#include "pkg/pkgwriter.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
|
|
||||||
struct pkg_writer_t {
|
struct pkg_writer_t {
|
||||||
|
@ -96,7 +96,7 @@ pkg_writer_t *pkg_writer_open(const char *path, bool force)
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
wr->stream = cmp->compression_stream(cmp);
|
wr->stream = cmp->compression_stream(cmp, NULL);
|
||||||
if (wr->stream == NULL) {
|
if (wr->stream == NULL) {
|
||||||
fputs("error creating compressor stream for package header\n",
|
fputs("error creating compressor stream for package header\n",
|
||||||
stderr);
|
stderr);
|
||||||
|
@ -153,7 +153,7 @@ int pkg_writer_start_record(pkg_writer_t *wr, uint32_t magic,
|
||||||
if (write_header(wr))
|
if (write_header(wr))
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
wr->stream = cmp->compression_stream(cmp);
|
wr->stream = cmp->compression_stream(cmp, NULL);
|
||||||
if (wr->stream == NULL)
|
if (wr->stream == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -2,7 +2,7 @@
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "depgraph.h"
|
#include "pkg/pkglist.h"
|
||||||
|
|
||||||
static void remove_dependency(struct pkg_dep_list *list,
|
static void remove_dependency(struct pkg_dep_list *list,
|
||||||
struct pkg_dep_node *pkg)
|
struct pkg_dep_node *pkg)
|
|
@ -1,13 +1,8 @@
|
||||||
pkg_SOURCES = include/pkgformat.h include/pkgreader.h include/pkgio.h
|
pkg_SOURCES = main/command.h main/pkg.c main/command.c
|
||||||
pkg_SOURCES += include/compressor.h include/command.h include/pkgwriter.h
|
|
||||||
pkg_SOURCES += include/depgraph.h
|
|
||||||
pkg_SOURCES += main/pkg.c main/compressor.c main/command.c main/pkgreader.c
|
|
||||||
pkg_SOURCES += main/pkgwriter.c main/pkgio_rd_image_entry.c main/pkg_unpack.c
|
|
||||||
pkg_SOURCES += main/depgraph/collect.c main/depgraph/pkglist.c
|
|
||||||
pkg_SOURCES += main/depgraph/tsort.c
|
|
||||||
|
|
||||||
|
pkg_CPPFLAGS = $(AM_CPPFLAGS) -I$(top_srcdir)/main
|
||||||
pkg_CFLAGS = $(AM_CFLAGS)
|
pkg_CFLAGS = $(AM_CFLAGS)
|
||||||
pkg_LDADD = libutil.a libfilelist.a
|
pkg_LDADD = libpkg.a libutil.a libfilelist.a libcomp.a
|
||||||
|
|
||||||
##### commands #####
|
##### commands #####
|
||||||
|
|
||||||
|
@ -27,6 +22,8 @@ pkg_SOURCES += main/cmd/install.c
|
||||||
# buildstrategy command
|
# buildstrategy command
|
||||||
pkg_SOURCES += main/cmd/buildstrategy/buildstrategy.h
|
pkg_SOURCES += main/cmd/buildstrategy/buildstrategy.h
|
||||||
pkg_SOURCES += main/cmd/buildstrategy/buildstrategy.c
|
pkg_SOURCES += main/cmd/buildstrategy/buildstrategy.c
|
||||||
|
pkg_SOURCES += main/cmd/buildstrategy/srcpkg.c
|
||||||
|
pkg_SOURCES += main/cmd/buildstrategy/provider.c
|
||||||
|
|
||||||
# depgraph command
|
# depgraph command
|
||||||
pkg_SOURCES += main/cmd/depgraph.c
|
pkg_SOURCES += main/cmd/depgraph.c
|
||||||
|
@ -38,24 +35,12 @@ pkg_SOURCES += main/cmd/unpack.c
|
||||||
pkg_SOURCES += main/cmd/help.c
|
pkg_SOURCES += main/cmd/help.c
|
||||||
|
|
||||||
##### compressors #####
|
##### compressors #####
|
||||||
|
|
||||||
# dummy compressor
|
|
||||||
pkg_SOURCES += main/compressors/none.c
|
|
||||||
|
|
||||||
# zlib compressor
|
|
||||||
if WITH_ZLIB
|
|
||||||
pkg_SOURCES += main/compressors/zlib.c
|
|
||||||
|
|
||||||
pkg_CFLAGS += $(ZLIB_CFLAGS)
|
|
||||||
pkg_LDADD += $(ZLIB_LIBS)
|
|
||||||
endif
|
|
||||||
|
|
||||||
# lzma compressor
|
|
||||||
if WITH_LZMA
|
if WITH_LZMA
|
||||||
pkg_SOURCES += main/compressors/lzma.c
|
|
||||||
|
|
||||||
pkg_CFLAGS += $(XZ_CFLAGS)
|
|
||||||
pkg_LDADD += $(XZ_LIBS)
|
pkg_LDADD += $(XZ_LIBS)
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
if WITH_ZLIB
|
||||||
|
pkg_LDADD += $(ZLIB_LIBS)
|
||||||
|
endif
|
||||||
|
|
||||||
bin_PROGRAMS += pkg
|
bin_PROGRAMS += pkg
|
||||||
|
|
|
@ -37,27 +37,21 @@ static int foreach_line(const char *filename, line_handler_t cb)
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static hash_table_t tbl_provides;
|
|
||||||
static hash_table_t tbl_sourcepkgs;
|
|
||||||
|
|
||||||
static int handle_depends(const char *filename, size_t linenum,
|
static int handle_depends(const char *filename, size_t linenum,
|
||||||
const char *sourcepkg, const char *binpkg)
|
const char *sourcepkg, const char *binpkg)
|
||||||
{
|
{
|
||||||
source_pkg_t *src, *dep;
|
source_pkg_t *src, *dep;
|
||||||
size_t count;
|
size_t count;
|
||||||
void *new;
|
void *new;
|
||||||
|
(void)filename; (void)linenum;
|
||||||
|
|
||||||
src = hash_table_lookup(&tbl_sourcepkgs, sourcepkg);
|
src = src_pkg_get(sourcepkg);
|
||||||
if (src == NULL)
|
if (src == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
dep = hash_table_lookup(&tbl_provides, binpkg);
|
dep = provider_get(sourcepkg, binpkg);
|
||||||
if (dep == NULL) {
|
if (dep == NULL)
|
||||||
fprintf(stderr,
|
|
||||||
"%s: %zu: nothing provides '%s' required by '%s'\n",
|
|
||||||
filename, linenum, binpkg, sourcepkg);
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
|
||||||
|
|
||||||
if ((src->num_depends % 10) == 0) {
|
if ((src->num_depends % 10) == 0) {
|
||||||
count = src->num_depends + 10;
|
count = src->num_depends + 10;
|
||||||
|
@ -78,105 +72,30 @@ static int handle_depends(const char *filename, size_t linenum,
|
||||||
static int handle_provides(const char *filename, size_t linenum,
|
static int handle_provides(const char *filename, size_t linenum,
|
||||||
const char *sourcepkg, const char *binpkg)
|
const char *sourcepkg, const char *binpkg)
|
||||||
{
|
{
|
||||||
source_pkg_t *src = NULL;
|
(void)filename; (void)linenum;
|
||||||
|
|
||||||
src = hash_table_lookup(&tbl_provides, binpkg);
|
return provider_add(sourcepkg, binpkg);
|
||||||
if (src != NULL) {
|
}
|
||||||
fprintf(stderr,
|
|
||||||
"%s: %zu: %s: package already provided by %s\n",
|
|
||||||
filename, linenum, binpkg, src->name);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
src = hash_table_lookup(&tbl_sourcepkgs, sourcepkg);
|
static int handle_prefere(const char *filename, size_t linenum,
|
||||||
|
const char *binpkg, const char *sourcepkg)
|
||||||
|
{
|
||||||
|
(void)filename; (void)linenum;
|
||||||
|
|
||||||
if (src == NULL) {
|
return provider_add_prefered(binpkg, sourcepkg);
|
||||||
src = calloc(1, sizeof(*src));
|
|
||||||
if (src == NULL)
|
|
||||||
goto fail_oom;
|
|
||||||
|
|
||||||
src->name = strdup(sourcepkg);
|
|
||||||
if (src->name == NULL)
|
|
||||||
goto fail_oom;
|
|
||||||
|
|
||||||
if (hash_table_set(&tbl_sourcepkgs, sourcepkg, src))
|
|
||||||
goto fail;
|
|
||||||
}
|
|
||||||
|
|
||||||
return hash_table_set(&tbl_provides, binpkg, src);
|
|
||||||
fail_oom:
|
|
||||||
fputs("out of memory\n", stderr);
|
|
||||||
fail:
|
|
||||||
if (src != NULL)
|
|
||||||
free(src->name);
|
|
||||||
free(src);
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
{ "provides", no_argument, NULL, 'p' },
|
{ "prefere", required_argument, NULL, 'P' },
|
||||||
{ "depends", no_argument, NULL, 'd' },
|
{ "provides", required_argument, NULL, 'p' },
|
||||||
|
{ "depends", required_argument, NULL, 'd' },
|
||||||
|
{ "graph", no_argument, NULL, 'g' },
|
||||||
{ NULL, 0, NULL, 0 },
|
{ NULL, 0, NULL, 0 },
|
||||||
};
|
};
|
||||||
|
|
||||||
static const char *short_opts = "p:d:";
|
static const char *short_opts = "p:d:P:g";
|
||||||
|
|
||||||
static int process_args(int argc, char **argv)
|
|
||||||
{
|
|
||||||
const char *provides = NULL, *depends = NULL;
|
|
||||||
int i;
|
|
||||||
|
|
||||||
for (;;) {
|
|
||||||
i = getopt_long(argc, argv, short_opts, long_opts, NULL);
|
|
||||||
if (i == -1)
|
|
||||||
break;
|
|
||||||
|
|
||||||
switch (i) {
|
|
||||||
case 'p':
|
|
||||||
provides = optarg;
|
|
||||||
break;
|
|
||||||
case 'd':
|
|
||||||
depends = optarg;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
goto fail_arg;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (optind >= argc) {
|
|
||||||
fputs("no packages specified\n", stderr);
|
|
||||||
goto fail_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (provides == NULL) {
|
|
||||||
fputs("no source package provides specified\n", stderr);
|
|
||||||
goto fail_arg;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (hash_table_init(&tbl_provides, 1024))
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
|
|
||||||
if (hash_table_init(&tbl_sourcepkgs, 1024))
|
|
||||||
goto fail_provides;
|
|
||||||
|
|
||||||
if (foreach_line(provides, handle_provides))
|
|
||||||
goto fail_srcpkg;
|
|
||||||
|
|
||||||
if (depends != NULL && foreach_line(depends, handle_depends) != 0)
|
|
||||||
goto fail_srcpkg;
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
fail_srcpkg:
|
|
||||||
hash_table_cleanup(&tbl_sourcepkgs);
|
|
||||||
fail_provides:
|
|
||||||
hash_table_cleanup(&tbl_provides);
|
|
||||||
return -1;
|
|
||||||
fail_arg:
|
|
||||||
tell_read_help(argv[0]);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void pkg_mark_deps(source_pkg_t *pkg)
|
static void pkg_mark_deps(source_pkg_t *pkg)
|
||||||
{
|
{
|
||||||
|
@ -193,98 +112,89 @@ static void pkg_mark_deps(source_pkg_t *pkg)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static int remove_untagged(void *usr, const char *name, void *p)
|
|
||||||
{
|
|
||||||
int mask = *((int *)usr);
|
|
||||||
source_pkg_t *pkg = p;
|
|
||||||
(void)name;
|
|
||||||
|
|
||||||
if ((pkg->flags & mask) == 0) {
|
|
||||||
free(pkg->name);
|
|
||||||
free(pkg->depends);
|
|
||||||
free(pkg);
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int remove_unmarked_deps(void *usr, const char *name, void *p)
|
|
||||||
{
|
|
||||||
source_pkg_t *pkg = p;
|
|
||||||
size_t i = 0;
|
|
||||||
(void)usr; (void)name;
|
|
||||||
|
|
||||||
while (i < pkg->num_depends) {
|
|
||||||
if ((pkg->depends[i]->flags & FLAG_BUILD_PKG) == 0) {
|
|
||||||
pkg->depends[i] = pkg->depends[pkg->num_depends - 1];
|
|
||||||
pkg->num_depends -= 1;
|
|
||||||
} else {
|
|
||||||
++i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int find_no_dep(void *usr, const char *name, void *p)
|
|
||||||
{
|
|
||||||
source_pkg_t *pkg = p;
|
|
||||||
int *found = usr;
|
|
||||||
|
|
||||||
if (pkg->num_depends == 0) {
|
|
||||||
printf("%s\n", name);
|
|
||||||
pkg->flags &= ~FLAG_BUILD_PKG;
|
|
||||||
*found = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
static int cmd_buildstrategy(int argc, char **argv)
|
static int cmd_buildstrategy(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i, ret = EXIT_FAILURE;
|
const char *provides = NULL, *depends = NULL, *prefere = NULL;
|
||||||
|
int i, ret = EXIT_FAILURE, mode = MODE_BUILD_ORDER;
|
||||||
source_pkg_t *pkg;
|
source_pkg_t *pkg;
|
||||||
|
|
||||||
if (process_args(argc, argv))
|
if (src_pkg_init())
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
|
|
||||||
for (i = optind; i < argc; ++i) {
|
if (provider_init())
|
||||||
pkg = hash_table_lookup(&tbl_provides, argv[i]);
|
goto out_src;
|
||||||
|
|
||||||
if (pkg == NULL) {
|
for (;;) {
|
||||||
fprintf(stderr, "nothing provides '%s'\n", argv[i]);
|
i = getopt_long(argc, argv, short_opts, long_opts, NULL);
|
||||||
goto out;
|
if (i == -1)
|
||||||
|
break;
|
||||||
|
|
||||||
|
switch (i) {
|
||||||
|
case 'P':
|
||||||
|
prefere = optarg;
|
||||||
|
break;
|
||||||
|
case 'p':
|
||||||
|
provides = optarg;
|
||||||
|
break;
|
||||||
|
case 'd':
|
||||||
|
depends = optarg;
|
||||||
|
break;
|
||||||
|
case 'g':
|
||||||
|
mode = MODE_BUILD_GRAPH;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
goto fail_arg;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind >= argc) {
|
||||||
|
fputs("no packages specified\n", stderr);
|
||||||
|
goto fail_arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (provides == NULL) {
|
||||||
|
fputs("no source package provides specified\n", stderr);
|
||||||
|
goto fail_arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (prefere != NULL && foreach_line(prefere, handle_prefere) != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (foreach_line(provides, handle_provides))
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
if (depends != NULL && foreach_line(depends, handle_depends) != 0)
|
||||||
|
goto out;
|
||||||
|
|
||||||
|
for (i = optind; i < argc; ++i) {
|
||||||
|
pkg = provider_get(NULL, argv[i]);
|
||||||
|
if (pkg == NULL)
|
||||||
|
goto out;
|
||||||
|
|
||||||
pkg_mark_deps(pkg);
|
pkg_mark_deps(pkg);
|
||||||
}
|
}
|
||||||
|
|
||||||
i = FLAG_BUILD_PKG;
|
switch (mode) {
|
||||||
hash_table_foreach(&tbl_sourcepkgs, &i, remove_untagged);
|
case MODE_BUILD_GRAPH:
|
||||||
|
fputs("digraph buildgraph {\n\tcompound=true;\n", stdout);
|
||||||
while (tbl_sourcepkgs.count > 0) {
|
src_pkg_print_graph_cluster();
|
||||||
i = 0;
|
fputs("}\n", stdout);
|
||||||
hash_table_foreach(&tbl_sourcepkgs, &i, find_no_dep);
|
break;
|
||||||
if (!i) {
|
default:
|
||||||
fputs("cycle detected in package dependencies!\n",
|
if (src_pkg_output_build_order())
|
||||||
stderr);
|
|
||||||
goto out;
|
goto out;
|
||||||
}
|
break;
|
||||||
|
|
||||||
hash_table_foreach(&tbl_sourcepkgs, NULL, remove_unmarked_deps);
|
|
||||||
|
|
||||||
i = FLAG_BUILD_PKG;
|
|
||||||
hash_table_foreach(&tbl_sourcepkgs, &i, remove_untagged);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = EXIT_SUCCESS;
|
ret = EXIT_SUCCESS;
|
||||||
out:
|
out:
|
||||||
i = 0;
|
provider_cleanup();
|
||||||
hash_table_foreach(&tbl_sourcepkgs, &i, remove_untagged);
|
out_src:
|
||||||
hash_table_cleanup(&tbl_sourcepkgs);
|
src_pkg_cleanup();
|
||||||
hash_table_cleanup(&tbl_provides);
|
|
||||||
return ret;
|
return ret;
|
||||||
|
fail_arg:
|
||||||
|
tell_read_help(argv[0]);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
|
|
||||||
static command_t buildstrategy = {
|
static command_t buildstrategy = {
|
||||||
|
@ -306,7 +216,15 @@ static command_t buildstrategy = {
|
||||||
" binary package.\n"
|
" binary package.\n"
|
||||||
" --depends, -d <file> A two column CSV file. Each line contains the name\n"
|
" --depends, -d <file> A two column CSV file. Each line contains the name\n"
|
||||||
" of a source package and a binary package that it\n"
|
" of a source package and a binary package that it\n"
|
||||||
" requires to build.\n",
|
" requires to build.\n"
|
||||||
|
" --prefere, -P <file> A two column CSV file. Each line contains the name\n"
|
||||||
|
" of a binary package and a source package that\n"
|
||||||
|
" produces this binary. If the `--provides` file\n"
|
||||||
|
" specifies that more than one source pacakge\n"
|
||||||
|
" provides a binary package, this file contains the\n"
|
||||||
|
" prefered one we should use.\n"
|
||||||
|
" --graph, -g Instead of printing out an ordered list, produce\n"
|
||||||
|
" a dot graph of the source packages to be built.\n",
|
||||||
.run_cmd = cmd_buildstrategy,
|
.run_cmd = cmd_buildstrategy,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -17,7 +17,13 @@ enum {
|
||||||
FLAG_BUILD_PKG = 0x01,
|
FLAG_BUILD_PKG = 0x01,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
MODE_BUILD_ORDER = 0,
|
||||||
|
MODE_BUILD_GRAPH,
|
||||||
|
};
|
||||||
|
|
||||||
typedef struct source_pkg_t {
|
typedef struct source_pkg_t {
|
||||||
|
struct source_pkg_t *next;
|
||||||
char *name;
|
char *name;
|
||||||
|
|
||||||
struct source_pkg_t **depends;
|
struct source_pkg_t **depends;
|
||||||
|
@ -26,4 +32,24 @@ typedef struct source_pkg_t {
|
||||||
int flags;
|
int flags;
|
||||||
} source_pkg_t;
|
} source_pkg_t;
|
||||||
|
|
||||||
|
int src_pkg_init(void);
|
||||||
|
|
||||||
|
void src_pkg_cleanup(void);
|
||||||
|
|
||||||
|
source_pkg_t *src_pkg_get(const char *name);
|
||||||
|
|
||||||
|
int src_pkg_output_build_order(void);
|
||||||
|
|
||||||
|
int provider_init(void);
|
||||||
|
|
||||||
|
void provider_cleanup(void);
|
||||||
|
|
||||||
|
int provider_add(const char *sourcepkg, const char *binpkg);
|
||||||
|
|
||||||
|
int provider_add_prefered(const char *binpkg, const char *sourcepkg);
|
||||||
|
|
||||||
|
source_pkg_t *provider_get(const char *parent, const char *binpkg);
|
||||||
|
|
||||||
|
void src_pkg_print_graph_cluster(void);
|
||||||
|
|
||||||
#endif /* BUILDSTRATEGY_H */
|
#endif /* BUILDSTRATEGY_H */
|
||||||
|
|
110
main/cmd/buildstrategy/provider.c
Normal file
110
main/cmd/buildstrategy/provider.c
Normal file
|
@ -0,0 +1,110 @@
|
||||||
|
/* SPDX-License-Identifier: ISC */
|
||||||
|
#include "buildstrategy.h"
|
||||||
|
|
||||||
|
static hash_table_t tbl_provides;
|
||||||
|
static hash_table_t tbl_preferes;
|
||||||
|
|
||||||
|
int provider_init(void)
|
||||||
|
{
|
||||||
|
if (hash_table_init(&tbl_provides, 1024))
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
if (hash_table_init(&tbl_preferes, 1024)) {
|
||||||
|
hash_table_cleanup(&tbl_provides);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void provider_cleanup(void)
|
||||||
|
{
|
||||||
|
hash_table_cleanup(&tbl_provides);
|
||||||
|
hash_table_cleanup(&tbl_preferes);
|
||||||
|
}
|
||||||
|
|
||||||
|
int provider_add(const char *sourcepkg, const char *binpkg)
|
||||||
|
{
|
||||||
|
source_pkg_t *head = hash_table_lookup(&tbl_provides, binpkg), *src;
|
||||||
|
|
||||||
|
for (src = head; src != NULL; src = src->next) {
|
||||||
|
if (strcmp(src->name, sourcepkg) == 0)
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
src = src_pkg_get(sourcepkg);
|
||||||
|
if (src == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
src->next = head;
|
||||||
|
return hash_table_set(&tbl_provides, binpkg, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
int provider_add_prefered(const char *binpkg, const char *sourcepkg)
|
||||||
|
{
|
||||||
|
source_pkg_t *src = src_pkg_get(sourcepkg);
|
||||||
|
|
||||||
|
if (src == NULL)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
return hash_table_set(&tbl_preferes, binpkg, src);
|
||||||
|
}
|
||||||
|
|
||||||
|
source_pkg_t *provider_get(const char *parent, const char *binpkg)
|
||||||
|
{
|
||||||
|
source_pkg_t *spkg, *pref;
|
||||||
|
|
||||||
|
spkg = hash_table_lookup(&tbl_provides, binpkg);
|
||||||
|
if (spkg == NULL)
|
||||||
|
goto fail_none;
|
||||||
|
|
||||||
|
pref = hash_table_lookup(&tbl_preferes, binpkg);
|
||||||
|
|
||||||
|
if (spkg->next != NULL) {
|
||||||
|
if (pref == NULL)
|
||||||
|
goto fail_no_pref;
|
||||||
|
|
||||||
|
while (spkg != NULL && strcmp(spkg->name, pref->name) != 0) {
|
||||||
|
spkg = spkg->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (spkg == NULL) {
|
||||||
|
spkg = hash_table_lookup(&tbl_provides, binpkg);
|
||||||
|
goto fail_provider;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (pref != NULL && strcmp(spkg->name, pref->name) != 0)
|
||||||
|
goto fail_provider;
|
||||||
|
}
|
||||||
|
|
||||||
|
return spkg;
|
||||||
|
fail_none:
|
||||||
|
fprintf(stderr, "No source package provides binary package '%s'.\n\n",
|
||||||
|
binpkg);
|
||||||
|
goto fail;
|
||||||
|
fail_provider:
|
||||||
|
fprintf(stderr,
|
||||||
|
"Preferred provider for binary package '%s' is set to\n"
|
||||||
|
"source package '%s', which does not provide '%s'.\n\n",
|
||||||
|
binpkg, pref->name, binpkg);
|
||||||
|
goto fail_list_providers;
|
||||||
|
fail_no_pref:
|
||||||
|
fprintf(stderr, "No preferred provider set for "
|
||||||
|
"binary package '%s'.\n\n", binpkg);
|
||||||
|
goto fail_list_providers;
|
||||||
|
fail_list_providers:
|
||||||
|
fprintf(stderr, "The following source packages provide the "
|
||||||
|
"binary package '%s':\n\n", binpkg);
|
||||||
|
while (spkg != NULL) {
|
||||||
|
fprintf(stderr, "\t%s\n", spkg->name);
|
||||||
|
spkg = spkg->next;
|
||||||
|
}
|
||||||
|
fputc('\n', stderr);
|
||||||
|
goto fail;
|
||||||
|
fail:
|
||||||
|
if (parent != NULL) {
|
||||||
|
fprintf(stderr, "Binary package '%s' is required to "
|
||||||
|
"build source package '%s'\n", binpkg, parent);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
145
main/cmd/buildstrategy/srcpkg.c
Normal file
145
main/cmd/buildstrategy/srcpkg.c
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
/* SPDX-License-Identifier: ISC */
|
||||||
|
#include "buildstrategy.h"
|
||||||
|
|
||||||
|
static hash_table_t tbl_sourcepkgs;
|
||||||
|
|
||||||
|
static int src_pkg_destroy(void *usr, const char *name, void *p)
|
||||||
|
{
|
||||||
|
source_pkg_t *pkg = p;
|
||||||
|
(void)name; (void)usr;
|
||||||
|
|
||||||
|
free(pkg->name);
|
||||||
|
free(pkg->depends);
|
||||||
|
free(pkg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int src_pkg_init(void)
|
||||||
|
{
|
||||||
|
return hash_table_init(&tbl_sourcepkgs, 1024);
|
||||||
|
}
|
||||||
|
|
||||||
|
void src_pkg_cleanup(void)
|
||||||
|
{
|
||||||
|
hash_table_foreach(&tbl_sourcepkgs, NULL, src_pkg_destroy);
|
||||||
|
hash_table_cleanup(&tbl_sourcepkgs);
|
||||||
|
}
|
||||||
|
|
||||||
|
source_pkg_t *src_pkg_get(const char *name)
|
||||||
|
{
|
||||||
|
source_pkg_t *src = hash_table_lookup(&tbl_sourcepkgs, name);
|
||||||
|
|
||||||
|
if (src == NULL) {
|
||||||
|
src = calloc(1, sizeof(*src));
|
||||||
|
if (src == NULL)
|
||||||
|
goto fail_oom;
|
||||||
|
|
||||||
|
src->name = strdup(name);
|
||||||
|
if (src->name == NULL)
|
||||||
|
goto fail_oom;
|
||||||
|
|
||||||
|
if (hash_table_set(&tbl_sourcepkgs, name, src))
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
return src;
|
||||||
|
fail_oom:
|
||||||
|
fputs("out of memory\n", stderr);
|
||||||
|
fail:
|
||||||
|
if (src != NULL)
|
||||||
|
free(src->name);
|
||||||
|
free(src);
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_untagged(void *usr, const char *name, void *p)
|
||||||
|
{
|
||||||
|
int mask = *((int *)usr);
|
||||||
|
source_pkg_t *pkg = p;
|
||||||
|
(void)name;
|
||||||
|
|
||||||
|
if ((pkg->flags & mask) == 0) {
|
||||||
|
free(pkg->name);
|
||||||
|
free(pkg->depends);
|
||||||
|
free(pkg);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int find_no_dep(void *usr, const char *name, void *p)
|
||||||
|
{
|
||||||
|
source_pkg_t *pkg = p;
|
||||||
|
int *found = usr;
|
||||||
|
|
||||||
|
if (pkg->num_depends == 0) {
|
||||||
|
printf("%s\n", name);
|
||||||
|
pkg->flags &= ~FLAG_BUILD_PKG;
|
||||||
|
*found = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int remove_unmarked_deps(void *usr, const char *name, void *p)
|
||||||
|
{
|
||||||
|
source_pkg_t *pkg = p;
|
||||||
|
size_t i = 0;
|
||||||
|
(void)usr; (void)name;
|
||||||
|
|
||||||
|
while (i < pkg->num_depends) {
|
||||||
|
if ((pkg->depends[i]->flags & FLAG_BUILD_PKG) == 0) {
|
||||||
|
pkg->depends[i] = pkg->depends[pkg->num_depends - 1];
|
||||||
|
pkg->num_depends -= 1;
|
||||||
|
} else {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int src_pkg_output_build_order(void)
|
||||||
|
{
|
||||||
|
int i = FLAG_BUILD_PKG;
|
||||||
|
|
||||||
|
hash_table_foreach(&tbl_sourcepkgs, &i, remove_untagged);
|
||||||
|
|
||||||
|
while (tbl_sourcepkgs.count > 0) {
|
||||||
|
i = 0;
|
||||||
|
hash_table_foreach(&tbl_sourcepkgs, &i, find_no_dep);
|
||||||
|
if (!i) {
|
||||||
|
fputs("cycle detected in package dependencies!\n",
|
||||||
|
stderr);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
hash_table_foreach(&tbl_sourcepkgs, NULL, remove_unmarked_deps);
|
||||||
|
|
||||||
|
i = FLAG_BUILD_PKG;
|
||||||
|
hash_table_foreach(&tbl_sourcepkgs, &i, remove_untagged);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int print_cluster(void *usr, const char *name, void *p)
|
||||||
|
{
|
||||||
|
source_pkg_t *pkg = p;
|
||||||
|
size_t i;
|
||||||
|
(void)usr;
|
||||||
|
|
||||||
|
if (!(pkg->flags & FLAG_BUILD_PKG))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
for (i = 0; i < pkg->num_depends; ++i) {
|
||||||
|
printf("\t\"%s\" -> \"%s\"\n",
|
||||||
|
name, pkg->depends[i]->name);
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void src_pkg_print_graph_cluster(void)
|
||||||
|
{
|
||||||
|
hash_table_foreach(&tbl_sourcepkgs, NULL, print_cluster);
|
||||||
|
}
|
|
@ -7,8 +7,9 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
#include "depgraph.h"
|
#include "pkg/pkglist.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
{ "no-dependencies", no_argument, NULL, 'd' },
|
{ "no-dependencies", no_argument, NULL, 'd' },
|
||||||
|
@ -37,7 +38,7 @@ static void print_dot_graph(struct pkg_dep_list *list)
|
||||||
|
|
||||||
static int cmd_depgraph(int argc, char **argv)
|
static int cmd_depgraph(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i, repofd = AT_FDCWD, ret = EXIT_FAILURE;
|
int i, repofd = -1, ret = EXIT_FAILURE;
|
||||||
struct pkg_dep_list list;
|
struct pkg_dep_list list;
|
||||||
bool resolve_deps = true;
|
bool resolve_deps = true;
|
||||||
|
|
||||||
|
@ -53,7 +54,7 @@ static int cmd_depgraph(int argc, char **argv)
|
||||||
resolve_deps = false;
|
resolve_deps = false;
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
if (repofd != AT_FDCWD) {
|
if (repofd != -1) {
|
||||||
fputs("repo specified more than once\n",
|
fputs("repo specified more than once\n",
|
||||||
stderr);
|
stderr);
|
||||||
tell_read_help(argv[0]);
|
tell_read_help(argv[0]);
|
||||||
|
@ -71,6 +72,14 @@ static int cmd_depgraph(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (repofd == -1) {
|
||||||
|
repofd = open(REPODIR, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (repofd < 0) {
|
||||||
|
perror(REPODIR);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = optind; i < argc; ++i) {
|
for (i = optind; i < argc; ++i) {
|
||||||
if (append_pkg(&list, argv[i]) == NULL)
|
if (append_pkg(&list, argv[i]) == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -84,7 +93,7 @@ static int cmd_depgraph(int argc, char **argv)
|
||||||
print_dot_graph(&list);
|
print_dot_graph(&list);
|
||||||
ret = EXIT_SUCCESS;
|
ret = EXIT_SUCCESS;
|
||||||
out:
|
out:
|
||||||
if (repofd != AT_FDCWD)
|
if (repofd != -1)
|
||||||
close(repofd);
|
close(repofd);
|
||||||
pkg_list_cleanup(&list);
|
pkg_list_cleanup(&list);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -101,6 +110,7 @@ static command_t depgraph = {
|
||||||
"Possible options:\n"
|
"Possible options:\n"
|
||||||
" --repo-dir, -R <path> Specify the input repository path to fetch the\n"
|
" --repo-dir, -R <path> Specify the input repository path to fetch the\n"
|
||||||
" packages from.\n"
|
" packages from.\n"
|
||||||
|
" If not set, defaults to " REPODIR ".\n"
|
||||||
" --no-dependencies, -d Do not resolve dependencies, only process the\n"
|
" --no-dependencies, -d Do not resolve dependencies, only process the\n"
|
||||||
" packages listed on the command line.\n",
|
" packages listed on the command line.\n",
|
||||||
.run_cmd = cmd_depgraph,
|
.run_cmd = cmd_depgraph,
|
||||||
|
|
|
@ -27,9 +27,7 @@ static int cmd_dump(int argc, char **argv)
|
||||||
switch (i) {
|
switch (i) {
|
||||||
case 'l':
|
case 'l':
|
||||||
flags |= DUMP_TOC;
|
flags |= DUMP_TOC;
|
||||||
if (strcmp(optarg, "sqfs") == 0) {
|
if (strcmp(optarg, "initrd") == 0) {
|
||||||
format = TOC_FORMAT_SQFS;
|
|
||||||
} else if (strcmp(optarg, "initrd") == 0) {
|
|
||||||
format = TOC_FORMAT_INITRD;
|
format = TOC_FORMAT_INITRD;
|
||||||
} else if (strcmp(optarg, "pkg") == 0) {
|
} else if (strcmp(optarg, "pkg") == 0) {
|
||||||
format = TOC_FORMAT_PKG;
|
format = TOC_FORMAT_PKG;
|
||||||
|
@ -108,10 +106,6 @@ static command_t dump = {
|
||||||
" If \"detail\" is specified, a human readable,\n"
|
" If \"detail\" is specified, a human readable,\n"
|
||||||
" pretty printed format with details is used.\n"
|
" pretty printed format with details is used.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" If \"sqfs\" is specified, a squashfs pseudo\n"
|
|
||||||
" file is genareated for setting permissions\n"
|
|
||||||
" bits and ownership appropriately.\n"
|
|
||||||
"\n"
|
|
||||||
" If \"initrd\" is specified, the format of\n"
|
" If \"initrd\" is specified, the format of\n"
|
||||||
" Linux gen_init_cpio is produced.\n"
|
" Linux gen_init_cpio is produced.\n"
|
||||||
"\n"
|
"\n"
|
||||||
|
|
|
@ -12,10 +12,11 @@
|
||||||
|
|
||||||
#include "filelist/image_entry.h"
|
#include "filelist/image_entry.h"
|
||||||
|
|
||||||
#include "pkgformat.h"
|
#include "pkg/pkgformat.h"
|
||||||
#include "pkgreader.h"
|
#include "pkg/pkgreader.h"
|
||||||
|
#include "pkg/pkgio.h"
|
||||||
|
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "pkgio.h"
|
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
DUMP_TOC = 0x01,
|
DUMP_TOC = 0x01,
|
||||||
|
|
|
@ -7,10 +7,11 @@
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
|
|
||||||
|
#include "pkg/pkglist.h"
|
||||||
|
#include "pkg/pkgio.h"
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
#include "depgraph.h"
|
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "pkgio.h"
|
#include "config.h"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
INSTALL_MODE_INSTALL = 0,
|
INSTALL_MODE_INSTALL = 0,
|
||||||
|
@ -95,8 +96,8 @@ static int list_files(int repofd, const char *rootdir, TOC_FORMAT format,
|
||||||
|
|
||||||
static int cmd_install(int argc, char **argv)
|
static int cmd_install(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int i, rootfd = AT_FDCWD, repofd = AT_FDCWD, flags = 0;
|
|
||||||
int ret = EXIT_FAILURE, mode = INSTALL_MODE_INSTALL;
|
int ret = EXIT_FAILURE, mode = INSTALL_MODE_INSTALL;
|
||||||
|
int i, rootfd = -1, repofd = -1, flags = 0;
|
||||||
TOC_FORMAT format = TOC_FORMAT_PRETTY;
|
TOC_FORMAT format = TOC_FORMAT_PRETTY;
|
||||||
const char *rootdir = NULL;
|
const char *rootdir = NULL;
|
||||||
struct pkg_dep_list list;
|
struct pkg_dep_list list;
|
||||||
|
@ -118,9 +119,7 @@ static int cmd_install(int argc, char **argv)
|
||||||
break;
|
break;
|
||||||
case 'l':
|
case 'l':
|
||||||
mode = INSTALL_MODE_LIST_FILES;
|
mode = INSTALL_MODE_LIST_FILES;
|
||||||
if (strcmp(optarg, "sqfs") == 0) {
|
if (strcmp(optarg, "initrd") == 0) {
|
||||||
format = TOC_FORMAT_SQFS;
|
|
||||||
} else if (strcmp(optarg, "initrd") == 0) {
|
|
||||||
format = TOC_FORMAT_INITRD;
|
format = TOC_FORMAT_INITRD;
|
||||||
} else if (strcmp(optarg, "pkg") == 0) {
|
} else if (strcmp(optarg, "pkg") == 0) {
|
||||||
format = TOC_FORMAT_PKG;
|
format = TOC_FORMAT_PKG;
|
||||||
|
@ -133,7 +132,7 @@ static int cmd_install(int argc, char **argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'R':
|
case 'R':
|
||||||
if (repofd != AT_FDCWD) {
|
if (repofd != -1) {
|
||||||
fputs("repo specified more than once\n",
|
fputs("repo specified more than once\n",
|
||||||
stderr);
|
stderr);
|
||||||
tell_read_help(argv[0]);
|
tell_read_help(argv[0]);
|
||||||
|
@ -146,7 +145,7 @@ static int cmd_install(int argc, char **argv)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
if (rootfd != AT_FDCWD) {
|
if (rootfd != -1) {
|
||||||
fputs("root specified more than once\n",
|
fputs("root specified more than once\n",
|
||||||
stderr);
|
stderr);
|
||||||
tell_read_help(argv[0]);
|
tell_read_help(argv[0]);
|
||||||
|
@ -182,6 +181,22 @@ static int cmd_install(int argc, char **argv)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (repofd == -1) {
|
||||||
|
repofd = open(REPODIR, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (repofd < 0) {
|
||||||
|
perror(REPODIR);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (rootfd == -1) {
|
||||||
|
rootfd = open(INSTALLROOT, O_RDONLY | O_DIRECTORY);
|
||||||
|
if (rootfd < 0) {
|
||||||
|
perror(INSTALLROOT);
|
||||||
|
goto out;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
for (i = optind; i < argc; ++i) {
|
for (i = optind; i < argc; ++i) {
|
||||||
if (append_pkg(&list, argv[i]) == NULL)
|
if (append_pkg(&list, argv[i]) == NULL)
|
||||||
goto out;
|
goto out;
|
||||||
|
@ -211,9 +226,9 @@ static int cmd_install(int argc, char **argv)
|
||||||
|
|
||||||
ret = EXIT_SUCCESS;
|
ret = EXIT_SUCCESS;
|
||||||
out:
|
out:
|
||||||
if (rootfd != AT_FDCWD)
|
if (rootfd != -1)
|
||||||
close(rootfd);
|
close(rootfd);
|
||||||
if (repofd != AT_FDCWD)
|
if (repofd != -1)
|
||||||
close(repofd);
|
close(repofd);
|
||||||
pkg_list_cleanup(&list);
|
pkg_list_cleanup(&list);
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -231,11 +246,12 @@ static command_t install = {
|
||||||
"Possible options:\n"
|
"Possible options:\n"
|
||||||
" --repo-dir, -R <path> Specify the input repository path to fetch the\n"
|
" --repo-dir, -R <path> Specify the input repository path to fetch the\n"
|
||||||
" packages from.\n"
|
" packages from.\n"
|
||||||
" --root, -r <path> A root directory to unpack the package. Default\n"
|
" If not set, defaults to " REPODIR ".\n"
|
||||||
" if not set is the current working directory.\n"
|
" --root, -r <path> A root directory to unpack the package.\n"
|
||||||
|
" If not set, defaults to " INSTALLROOT ".\n"
|
||||||
" --no-chown, -o Do not change ownership of the extracted data.\n"
|
" --no-chown, -o Do not change ownership of the extracted data.\n"
|
||||||
" Keep the uid/gid of the user who runs the \n"
|
" Keep the uid/gid of the user who runs the \n"
|
||||||
" program."
|
" program.\n"
|
||||||
" --no-chmod, -m Do not change permission flags of the extarcted\n"
|
" --no-chmod, -m Do not change permission flags of the extarcted\n"
|
||||||
" data. Use 0644 for all files and 0755 for all\n"
|
" data. Use 0644 for all files and 0755 for all\n"
|
||||||
" directories.\n"
|
" directories.\n"
|
||||||
|
@ -252,10 +268,6 @@ static command_t install = {
|
||||||
" If \"detail\" is specified, a human readable,\n"
|
" If \"detail\" is specified, a human readable,\n"
|
||||||
" pretty printed format with details is used.\n"
|
" pretty printed format with details is used.\n"
|
||||||
"\n"
|
"\n"
|
||||||
" If \"sqfs\" is specified, a squashfs pseudo\n"
|
|
||||||
" file is genareated for setting permissions bits\n"
|
|
||||||
" and ownership appropriately.\n"
|
|
||||||
"\n"
|
|
||||||
" If \"initrd\" is specified, the format of Linux\n"
|
" If \"initrd\" is specified, the format of Linux\n"
|
||||||
" gen_init_cpio is produced.\n",
|
" gen_init_cpio is produced.\n",
|
||||||
.run_cmd = cmd_install,
|
.run_cmd = cmd_install,
|
||||||
|
|
|
@ -13,6 +13,22 @@ static void oom(const char *filename, size_t linenum)
|
||||||
input_file_complain(filename, linenum, "out of memory");
|
input_file_complain(filename, linenum, "out of memory");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void unescape_name(char *name)
|
||||||
|
{
|
||||||
|
char *dst = name, *src = name + 1;
|
||||||
|
|
||||||
|
while (*src != '"' && *src != '\0') {
|
||||||
|
if (src[0] == '\\' && (src[1] == '\\' || src[1] == '"')) {
|
||||||
|
*(dst++) = src[1];
|
||||||
|
src += 2;
|
||||||
|
} else {
|
||||||
|
*(dst++) = *(src++);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*dst = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
static image_entry_t *filelist_mkentry(char *line, const char *filename,
|
static image_entry_t *filelist_mkentry(char *line, const char *filename,
|
||||||
size_t linenum, mode_t filetype)
|
size_t linenum, mode_t filetype)
|
||||||
{
|
{
|
||||||
|
@ -27,8 +43,23 @@ static image_entry_t *filelist_mkentry(char *line, const char *filename,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* name */
|
/* name */
|
||||||
for (i = 0; !isspace(line[i]) && line[i] != '\0'; ++i)
|
if (*line == '"') {
|
||||||
;
|
for (i = 1; line[i] != '"' && line[i] != '\0'; ++i) {
|
||||||
|
if (line[i] == '\\' &&
|
||||||
|
(line[i + 1] == '\\' || line[i + 1] == '"')) {
|
||||||
|
++i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (line[i++] != '"') {
|
||||||
|
input_file_complain(filename, linenum,
|
||||||
|
"missing \" after file name");
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (i = 0; !isspace(line[i]) && line[i] != '\0'; ++i)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
if (!isspace(line[i])) {
|
if (!isspace(line[i])) {
|
||||||
input_file_complain(filename, linenum,
|
input_file_complain(filename, linenum,
|
||||||
|
@ -43,6 +74,10 @@ static image_entry_t *filelist_mkentry(char *line, const char *filename,
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(ent->name, line, i);
|
memcpy(ent->name, line, i);
|
||||||
|
|
||||||
|
if (ent->name[0] == '"')
|
||||||
|
unescape_name(ent->name);
|
||||||
|
|
||||||
if (canonicalize_name(ent->name)) {
|
if (canonicalize_name(ent->name)) {
|
||||||
input_file_complain(filename, linenum, "invalid file name");
|
input_file_complain(filename, linenum, "invalid file name");
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -65,9 +65,7 @@ static int cmd_pack(int argc, char **argv)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (repodir == NULL) {
|
if (repodir == NULL) {
|
||||||
fputs("missing argument: repository directory\n", stderr);
|
repodir = REPODIR;
|
||||||
tell_read_help(argv[0]);
|
|
||||||
return EXIT_FAILURE;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (optind < argc)
|
if (optind < argc)
|
||||||
|
@ -117,6 +115,7 @@ static command_t pack = {
|
||||||
" --file-list, -l <path> Specify a file containing a list of input files.\n"
|
" --file-list, -l <path> Specify a file containing a list of input files.\n"
|
||||||
" --repo-dir, -r <path> Specify the output repository path to store the\n"
|
" --repo-dir, -r <path> Specify the output repository path to store the\n"
|
||||||
" package in.\n"
|
" package in.\n"
|
||||||
|
" If not set, defaults to " REPODIR ".\n"
|
||||||
" --description, -d <path> Specify a file containing a description of the\n"
|
" --description, -d <path> Specify a file containing a description of the\n"
|
||||||
" package, including information such as package\n"
|
" package, including information such as package\n"
|
||||||
" dependencies, the actual package name, etc.\n"
|
" dependencies, the actual package name, etc.\n"
|
||||||
|
|
|
@ -21,10 +21,11 @@
|
||||||
|
|
||||||
#include "filelist/image_entry.h"
|
#include "filelist/image_entry.h"
|
||||||
|
|
||||||
#include "compressor.h"
|
#include "comp/compressor.h"
|
||||||
#include "pkgformat.h"
|
#include "pkg/pkgformat.h"
|
||||||
#include "pkgwriter.h"
|
#include "pkg/pkgwriter.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
|
#include "config.h"
|
||||||
|
|
||||||
typedef struct dependency_t {
|
typedef struct dependency_t {
|
||||||
struct dependency_t *next;
|
struct dependency_t *next;
|
||||||
|
|
|
@ -7,9 +7,9 @@
|
||||||
|
|
||||||
#include "util/util.h"
|
#include "util/util.h"
|
||||||
|
|
||||||
#include "pkgreader.h"
|
#include "pkg/pkgreader.h"
|
||||||
|
#include "pkg/pkgio.h"
|
||||||
#include "command.h"
|
#include "command.h"
|
||||||
#include "pkgio.h"
|
|
||||||
|
|
||||||
static const struct option long_opts[] = {
|
static const struct option long_opts[] = {
|
||||||
{ "root", required_argument, NULL, 'r' },
|
{ "root", required_argument, NULL, 'r' },
|
||||||
|
|
|
@ -1,32 +0,0 @@
|
||||||
/* SPDX-License-Identifier: ISC */
|
|
||||||
#include <string.h>
|
|
||||||
|
|
||||||
#include "compressor.h"
|
|
||||||
|
|
||||||
static compressor_t *list = NULL;
|
|
||||||
|
|
||||||
void compressor_register(compressor_t *compressor)
|
|
||||||
{
|
|
||||||
compressor->next = list;
|
|
||||||
list = compressor;
|
|
||||||
}
|
|
||||||
|
|
||||||
compressor_t *compressor_by_name(const char *name)
|
|
||||||
{
|
|
||||||
compressor_t *it = list;
|
|
||||||
|
|
||||||
while (it != NULL && strcmp(it->name, name) != 0)
|
|
||||||
it = it->next;
|
|
||||||
|
|
||||||
return it;
|
|
||||||
}
|
|
||||||
|
|
||||||
compressor_t *compressor_by_id(PKG_COMPRESSION id)
|
|
||||||
{
|
|
||||||
compressor_t *it = list;
|
|
||||||
|
|
||||||
while (it != NULL && it->id != id)
|
|
||||||
it = it->next;
|
|
||||||
|
|
||||||
return it;
|
|
||||||
}
|
|
Loading…
Reference in a new issue