summaryrefslogtreecommitdiff
path: root/lib/fstree/sort_by_file.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/fstree/sort_by_file.c')
-rw-r--r--lib/fstree/sort_by_file.c368
1 files changed, 0 insertions, 368 deletions
diff --git a/lib/fstree/sort_by_file.c b/lib/fstree/sort_by_file.c
deleted file mode 100644
index ed4a58c..0000000
--- a/lib/fstree/sort_by_file.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/* SPDX-License-Identifier: GPL-3.0-or-later */
-/*
- * sort_by_file.c
- *
- * Copyright (C) 2021 David Oberhollenzer <goliath@infraroot.at>
- */
-#include "config.h"
-
-#include "util/util.h"
-#include "fstree.h"
-#include "compat.h"
-
-#include "sqfs/block.h"
-
-#include <string.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-static int decode_priority(const char *filename, size_t line_no,
- char *line, sqfs_s64 *priority)
-{
- bool negative = false;
- size_t i = 0;
-
- if (line[0] == '-') {
- negative = true;
- i = 1;
- }
-
- if (!isdigit(line[i]))
- goto fail_number;
-
- *priority = 0;
-
- for (; isdigit(line[i]); ++i) {
- sqfs_s64 x = line[i] - '0';
-
- if ((*priority) >= ((0x7FFFFFFFFFFFFFFFL - x) / 10L))
- goto fail_ov;
-
- (*priority) = (*priority) * 10 + x;
- }
-
- if (!isspace(line[i]))
- goto fail_filename;
-
- while (isspace(line[i]))
- ++i;
-
- if (line[i] == '\0')
- goto fail_filename;
-
- if (negative)
- (*priority) = -(*priority);
-
- memmove(line, line + i, strlen(line + i) + 1);
- return 0;
-fail_number:
- fprintf(stderr, "%s: " PRI_SZ ": Line must start with "
- "numeric sort priority.\n",
- filename, line_no);
- return -1;
-fail_ov:
- fprintf(stderr, "%s: " PRI_SZ ": Numeric overflow in sort priority.\n",
- filename, line_no);
- return -1;
-fail_filename:
- fprintf(stderr, "%s: " PRI_SZ ": Expacted `<space> <filename>` "
- "after sort priority.\n",
- filename, line_no);
- return -1;
-}
-
-static int decode_filename(const char *filename, size_t line_no, char *buffer)
-{
- char *src, *dst;
-
- if (buffer[0] == '"') {
- src = buffer + 1;
- dst = buffer;
-
- for (;;) {
- if (src[0] == '\0')
- goto fail_match;
-
- if (src[0] == '"') {
- ++src;
- break;
- }
-
- if (src[0] == '\\') {
- switch (src[1]) {
- case '\\':
- *(dst++) = '\\';
- src += 2;
- break;
- case '"':
- *(dst++) = '"';
- src += 2;
- break;
- default:
- goto fail_escape;
- }
- } else {
- *(dst++) = *(src++);
- }
- }
-
- if (*src != '\0')
- return -1;
- }
-
- if (canonicalize_name(buffer))
- goto fail_canon;
- return 0;
-fail_canon:
- fprintf(stderr, "%s: " PRI_SZ ": Malformed filename.\n",
- filename, line_no);
- return -1;
-fail_escape:
- fprintf(stderr, "%s: " PRI_SZ ": Unknown escape sequence `\\%c` "
- "in filename.\n", filename, line_no, src[1]);
- return -1;
-fail_match:
- fprintf(stderr, "%s: " PRI_SZ ": Unmatched '\"' in filename.\n",
- filename, line_no);
- return -1;
-}
-
-static int decode_flags(const char *filename, size_t line_no, bool *do_glob,
- bool *path_glob, int *flags, char *line)
-{
- char *start = line;
-
- *do_glob = false;
- *path_glob = false;
- *flags = 0;
-
- if (*(line++) != '[')
- return 0;
-
- for (;;) {
- while (isspace(*line))
- ++line;
-
- if (*line == ']') {
- ++line;
- break;
- }
-
- if (strncmp(line, "glob_no_path", 12) == 0) {
- line += 12;
- *do_glob = true;
- *path_glob = false;
- } else if (strncmp(line, "glob", 4) == 0) {
- line += 4;
- *do_glob = true;
- *path_glob = true;
- } else if (strncmp(line, "dont_fragment", 13) == 0) {
- line += 13;
- (*flags) |= SQFS_BLK_DONT_FRAGMENT;
- } else if (strncmp(line, "align", 5) == 0) {
- line += 5;
- (*flags) |= SQFS_BLK_ALIGN;
- } else if (strncmp(line, "dont_compress", 13) == 0) {
- line += 13;
- (*flags) |= SQFS_BLK_DONT_COMPRESS;
- } else if (strncmp(line, "dont_deduplicate", 16) == 0) {
- line += 16;
- (*flags) |= SQFS_BLK_DONT_DEDUPLICATE;
- } else if (strncmp(line, "nosparse", 8) == 0) {
- line += 8;
- (*flags) |= SQFS_BLK_IGNORE_SPARSE;
- } else {
- goto fail_flag;
- }
-
- while (isspace(*line))
- ++line;
-
- if (*line == ']') {
- ++line;
- break;
- }
-
- if (*(line++) != ',')
- goto fail_sep;
- }
-
- if (!isspace(*line))
- goto fail_fname;
-
- while (isspace(*line))
- ++line;
-
- memmove(start, line, strlen(line) + 1);
- return 0;
-fail_fname:
- fprintf(stderr, "%s: " PRI_SZ ": Expected `<space> <filename>` "
- "after flag list.\n", filename, line_no);
- return -1;
-fail_sep:
- fprintf(stderr, "%s: " PRI_SZ ": Unexpected '%c' after flag.\n",
- filename, line_no, *line);
- return -1;
-fail_flag:
- fprintf(stderr, "%s: " PRI_SZ ": Unknown flag `%.3s...`.\n",
- filename, line_no, line);
- return -1;
-}
-
-static void sort_file_list(fstree_t *fs)
-{
- file_info_t *out = NULL, *out_last = NULL;
-
- while (fs->files != NULL) {
- sqfs_s64 lowest = fs->files->priority;
- file_info_t *it, *prev;
-
- for (it = fs->files; it != NULL; it = it->next) {
- if (it->priority < lowest)
- lowest = it->priority;
- }
-
- it = fs->files;
- prev = NULL;
-
- while (it != NULL) {
- if (it->priority != lowest) {
- prev = it;
- it = it->next;
- continue;
- }
-
- if (prev == NULL) {
- fs->files = it->next;
- } else {
- prev->next = it->next;
- }
-
- if (out == NULL) {
- out = it;
- } else {
- out_last->next = it;
- }
-
- out_last = it;
- it = it->next;
- out_last->next = NULL;
- }
- }
-
- fs->files = out;
-}
-
-int fstree_sort_files(fstree_t *fs, istream_t *sortfile)
-{
- const char *filename;
- size_t line_num = 1;
- file_info_t *it;
-
- for (it = fs->files; it != NULL; it = it->next) {
- it->priority = 0;
- it->flags = 0;
- it->already_matched = false;
- }
-
- filename = istream_get_filename(sortfile);
-
- for (;;) {
- bool do_glob, path_glob, have_match;
- char *line = NULL;
- sqfs_s64 priority;
- int ret, flags;
-
- ret = istream_get_line(sortfile, &line, &line_num,
- ISTREAM_LINE_LTRIM |
- ISTREAM_LINE_RTRIM |
- ISTREAM_LINE_SKIP_EMPTY);
- if (ret != 0) {
- free(line);
- if (ret < 0)
- return -1;
- break;
- }
-
- if (line[0] == '#') {
- free(line);
- continue;
- }
-
- if (decode_priority(filename, line_num, line, &priority)) {
- free(line);
- return -1;
- }
-
- if (decode_flags(filename, line_num, &do_glob, &path_glob,
- &flags, line)) {
- free(line);
- return -1;
- }
-
- if (decode_filename(filename, line_num, line)) {
- free(line);
- return -1;
- }
-
- have_match = false;
-
- for (it = fs->files; it != NULL; it = it->next) {
- tree_node_t *node;
- char *path;
-
- if (it->already_matched)
- continue;
-
- node = container_of(it, tree_node_t, data.file);
- path = fstree_get_path(node);
- if (path == NULL) {
- fprintf(stderr, "%s: " PRI_SZ ": out-of-memory\n",
- filename, line_num);
- free(line);
- return -1;
- }
-
- if (canonicalize_name(path)) {
- fprintf(stderr,
- "%s: " PRI_SZ ": [BUG] error "
- "reconstructing node path\n",
- filename, line_num);
- free(line);
- free(path);
- return -1;
- }
-
- if (do_glob) {
- ret = fnmatch(line, path,
- path_glob ? FNM_PATHNAME : 0);
-
- } else {
- ret = strcmp(path, line);
- }
-
- free(path);
-
- if (ret == 0) {
- have_match = true;
- it->flags = flags;
- it->priority = priority;
- it->already_matched = true;
-
- if (!do_glob)
- break;
- }
- }
-
- if (!have_match) {
- fprintf(stderr, "WARNING: %s: " PRI_SZ ": no match "
- "for '%s'.\n",
- filename, line_num, line);
- }
-
- free(line);
- }
-
- sort_file_list(fs);
- return 0;
-}