mirror of
https://github.com/lhearachel/narc.git
synced 2025-06-18 21:45:34 -04:00
feat(cli-create): Implement naix output
This commit is contained in:
parent
aa488232cf
commit
2d6a269985
32
cli/include/strbuild.h
Normal file
32
cli/include/strbuild.h
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Copyright 2024 <lhearachel@proton.me>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef NARC_STRBUILD_H
|
||||
#define NARC_STRBUILD_H
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
struct strbuild {
|
||||
char *s;
|
||||
size_t len;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
struct strbuild *strbuild_new(size_t capacity);
|
||||
void strbuild_del(struct strbuild *strbuild);
|
||||
int strbuild_cat(struct strbuild *strbuild, const char *s);
|
||||
int strbuild_sprintf(struct strbuild *strbuild, const char *fmt, ...);
|
||||
|
||||
#endif // NARC_STRBUILD_H
|
@ -30,8 +30,9 @@
|
||||
bool match_either(const char *s, const char *a, const char *b);
|
||||
char *basename(const char *path);
|
||||
|
||||
// NOTE: This routine performs a string allocation! The calling client is
|
||||
// NOTE: These routines perform a string allocation! The calling client is
|
||||
// responsible for freeing the result when they are finished with it!
|
||||
char *basename_extend(const char *path, const char *ext);
|
||||
char *basename_stem_extend(const char *path, const char *ext);
|
||||
|
||||
#endif // NARC_UTILS_H
|
||||
|
@ -14,6 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fnmatch.h>
|
||||
@ -27,6 +28,7 @@
|
||||
#include "defs/narc.h"
|
||||
#include "defs/vfs.h"
|
||||
|
||||
#include "strbuild.h"
|
||||
#include "strvec.h"
|
||||
#include "utils.h"
|
||||
|
||||
@ -56,6 +58,20 @@ static const char *options = ""
|
||||
" patterns which may be present in DIRECTORY but should\n"
|
||||
" not be added to the output."
|
||||
"";
|
||||
|
||||
static const char *naix_header = ""
|
||||
"/*\n"
|
||||
" * THIS FILE WAS AUTOMATICALLY GENERATED BY narc\n"
|
||||
" * DO NOT MODIFY!!!\n"
|
||||
" */\n"
|
||||
"#ifndef %s\n"
|
||||
"#define %s\n"
|
||||
"\n"
|
||||
"";
|
||||
|
||||
static const char *naix_member = "#define %s %d\n";
|
||||
|
||||
static const char *naix_footer = "\n#endif /* %s */\n";
|
||||
// clang-format on
|
||||
|
||||
struct options {
|
||||
@ -66,15 +82,12 @@ struct options {
|
||||
const char *ignore;
|
||||
};
|
||||
|
||||
struct array {
|
||||
char **elems;
|
||||
size_t count;
|
||||
size_t capacity;
|
||||
};
|
||||
|
||||
static int parse_opts(int *argc, const char ***argv, struct options *opts);
|
||||
static int pack(struct options *opts);
|
||||
static struct strvec *build_pack_list(DIR *dir, const char *order_fname, const char *ignore_fname);
|
||||
static struct strbuild *start_index(const char *target_fname, char **out_guard);
|
||||
static void add_to_index(struct strbuild *index, const char *fname, const size_t i);
|
||||
static void finish_index(struct strbuild *index, const char *guard);
|
||||
|
||||
int create(int argc, const char **argv)
|
||||
{
|
||||
@ -140,10 +153,11 @@ static int parse_opts(int *argc, const char ***argv, struct options *opts)
|
||||
static int pack(struct options *opts)
|
||||
{
|
||||
DIR *dir = NULL;
|
||||
FILE *fout = NULL;
|
||||
FILE *fout = NULL, *fnaix = NULL;
|
||||
char *cwd = NULL;
|
||||
struct narc *narc = NULL;
|
||||
struct vfs_pack_ctx *ctx = NULL;
|
||||
char *naix = basename_stem_extend(opts->output, "naix");
|
||||
|
||||
dir = opendir(opts->input);
|
||||
if (dir == NULL) {
|
||||
@ -155,6 +169,9 @@ static int pack(struct options *opts)
|
||||
FAIL("narc create: could not get current working directory: %s\n", strerror(errno));
|
||||
}
|
||||
|
||||
char guard[256] = {0};
|
||||
char *guard_p = &guard[0]; // just to make the compiler happy
|
||||
struct strbuild *index = start_index(naix, &guard_p);
|
||||
struct strvec *to_pack = build_pack_list(dir, opts->order, opts->ignore);
|
||||
|
||||
chdir(opts->input);
|
||||
@ -176,18 +193,29 @@ static int pack(struct options *opts)
|
||||
|
||||
fread(image, 1, fsize, f);
|
||||
narc_pack_file(ctx, image, fsize);
|
||||
add_to_index(index, to_pack->s[i], i);
|
||||
fclose(f);
|
||||
}
|
||||
narc = narc_pack(ctx);
|
||||
finish_index(index, guard);
|
||||
chdir(cwd);
|
||||
|
||||
if (opts->naix) {
|
||||
fnaix = fopen(naix, "w");
|
||||
if (fnaix == NULL) {
|
||||
FAIL("narc create: error while opening file “%s” for writing: %s\n", opts->output, strerror(errno));
|
||||
}
|
||||
fwrite(index->s, 1, index->len, fnaix);
|
||||
fclose(fnaix);
|
||||
}
|
||||
|
||||
fout = fopen(opts->output, "wb");
|
||||
if (fout == NULL) {
|
||||
FAIL("narc create: error while opening file “%s” for writing: %s\n", opts->output, strerror(errno));
|
||||
}
|
||||
|
||||
fwrite(narc, narc->size, 1, fout);
|
||||
|
||||
free(naix);
|
||||
free(cwd);
|
||||
free(narc);
|
||||
fclose(fout);
|
||||
@ -199,11 +227,16 @@ fail:
|
||||
fclose(fout);
|
||||
}
|
||||
|
||||
if (fnaix) {
|
||||
fclose(fnaix);
|
||||
}
|
||||
|
||||
if (dir) {
|
||||
closedir(dir);
|
||||
}
|
||||
|
||||
narc_pack_halt(ctx);
|
||||
free(naix);
|
||||
free(cwd);
|
||||
free(narc);
|
||||
return EXIT_FAILURE;
|
||||
@ -213,6 +246,7 @@ static struct strvec *build_pack_list(DIR *dir, const char *order_fname, const c
|
||||
{
|
||||
struct strvec *all_files = NULL, *ignored = NULL;
|
||||
|
||||
// Build the list of ordered files first. These are never ignored.
|
||||
all_files = strvec_new(5000);
|
||||
if (strvec_from_file(all_files, order_fname)) {
|
||||
goto cleanup_error;
|
||||
@ -270,3 +304,50 @@ cleanup_error:
|
||||
strvec_del(ignored);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static struct strbuild *start_index(const char *target_fname, char **out_guard)
|
||||
{
|
||||
char guard[256] = "NARC_";
|
||||
size_t i;
|
||||
char c, *p = &guard[5];
|
||||
for (i = 0; i < 250 && (c = target_fname[i]) != '\0'; i++) {
|
||||
if (c == '-' || c == '.' || c == '_') {
|
||||
*p = '_';
|
||||
p++;
|
||||
} else if (islower(c)) {
|
||||
*p = toupper(c);
|
||||
p++;
|
||||
} else if (isupper(c)) {
|
||||
*p = c;
|
||||
p++;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
strcpy(*out_guard, guard);
|
||||
|
||||
struct strbuild *str = strbuild_new(65536);
|
||||
strbuild_sprintf(str, naix_header, guard, guard);
|
||||
return str;
|
||||
}
|
||||
|
||||
static void add_to_index(struct strbuild *index, const char *fname, const size_t i)
|
||||
{
|
||||
char def_name[256];
|
||||
size_t j;
|
||||
char c, *p = def_name;
|
||||
for (j = 0; j < 256 && (c = fname[j]) != '\0'; j++, p++) {
|
||||
if (ispunct(c)) {
|
||||
*p = '_';
|
||||
} else {
|
||||
*p = c;
|
||||
}
|
||||
}
|
||||
*p = '\0';
|
||||
|
||||
strbuild_sprintf(index, naix_member, def_name, i);
|
||||
}
|
||||
|
||||
static void finish_index(struct strbuild *index, const char *guard)
|
||||
{
|
||||
strbuild_sprintf(index, naix_footer, guard);
|
||||
}
|
||||
|
70
cli/src/strbuild.c
Normal file
70
cli/src/strbuild.c
Normal file
@ -0,0 +1,70 @@
|
||||
/*
|
||||
* Copyright 2024 <lhearachel@proton.me>
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "strbuild.h"
|
||||
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
struct strbuild *strbuild_new(size_t capacity)
|
||||
{
|
||||
struct strbuild *s = malloc(sizeof(struct strbuild));
|
||||
|
||||
s->s = malloc(capacity);
|
||||
s->s[0] = '\0';
|
||||
s->len = 0;
|
||||
s->capacity = capacity;
|
||||
|
||||
return s;
|
||||
}
|
||||
|
||||
void strbuild_del(struct strbuild *strbuild)
|
||||
{
|
||||
free(strbuild->s);
|
||||
free(strbuild);
|
||||
}
|
||||
|
||||
int strbuild_cat(struct strbuild *strbuild, const char *s)
|
||||
{
|
||||
size_t next_len = strlen(s);
|
||||
if (strbuild->len + next_len > strbuild->capacity) {
|
||||
size_t next_cap = (strbuild->capacity + next_len) * 2;
|
||||
char *p = realloc(strbuild->s, next_cap);
|
||||
if (p == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strbuild->s = p;
|
||||
strbuild->capacity = next_cap;
|
||||
}
|
||||
|
||||
strcat(strbuild->s, s);
|
||||
strbuild->len += next_len;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int strbuild_sprintf(struct strbuild *strbuild, const char *fmt, ...)
|
||||
{
|
||||
char buf[1024];
|
||||
va_list args;
|
||||
va_start(args, fmt);
|
||||
vsprintf(buf, fmt, args);
|
||||
va_end(args);
|
||||
|
||||
return strbuild_cat(strbuild, buf);
|
||||
}
|
@ -41,6 +41,22 @@ char *basename_extend(const char *path, const char *ext)
|
||||
return buf;
|
||||
}
|
||||
|
||||
char *basename_stem_extend(const char *path, const char *ext)
|
||||
{
|
||||
char *p = strrchr(path, '/');
|
||||
if (p == NULL) {
|
||||
p = (char *)path;
|
||||
}
|
||||
|
||||
char *s = strrchr(p, '.');
|
||||
size_t stem_len = (s == NULL) ? strlen(p) : s - p;
|
||||
|
||||
char *buf = malloc(stem_len + strlen(ext) + 2);
|
||||
strncpy(buf, p, stem_len);
|
||||
sprintf(buf + stem_len, ".%s", ext);
|
||||
return buf;
|
||||
}
|
||||
|
||||
bool match_either(const char *s, const char *a, const char *b)
|
||||
{
|
||||
return (a != NULL && strcmp(s, a) == 0)
|
||||
|
Loading…
Reference in New Issue
Block a user