From: Robert Pengelly Date: Sun, 31 Aug 2025 21:10:33 +0000 (+0100) Subject: Added mke2nod X-Git-Url: https://git.candlhat.org/?a=commitdiff_plain;h=HEAD;p=e2fsprogs.git Added mke2nod --- diff --git a/Makefile.std b/Makefile.std index 2bdc10c..9d0263d 100644 --- a/Makefile.std +++ b/Makefile.std @@ -8,7 +8,7 @@ LD=pdld --no-insert-timestamp COPTS=-S -O2 -fno-common -ansi -I. -I../pdos/pdpclib -D__WIN32__ -D__NOBIVA__ -D__PDOS__ COBJ=cache.obj common.obj list.obj report.obj -all: clean mke2fs.exe e2cp.exe e2md.exe +all: clean mke2fs.exe e2cp.exe e2md.exe mke2nod.exe mke2fs.exe: mke2fs.obj $(COBJ) $(LD) -s -o mke2fs.exe ../pdos/pdpclib/w32start.obj mke2fs.obj $(COBJ) ../pdos/pdpclib/msvcrt.lib @@ -19,6 +19,9 @@ e2cp.exe: e2cp.obj $(COBJ) e2md.exe: e2md.obj $(COBJ) $(LD) -s -o e2md.exe ../pdos/pdpclib/w32start.obj e2md.obj $(COBJ) ../pdos/pdpclib/msvcrt.lib +mke2nod.exe: mke2nod.obj $(COBJ) + $(LD) -s -o mke2nod.exe ../pdos/pdpclib/w32start.obj mke2nod.obj $(COBJ) ../pdos/pdpclib/msvcrt.lib + .c.obj: $(CC) $(COPTS) $< $(AS) -o $@ $*.s @@ -29,3 +32,4 @@ clean: rm -f mke2fs.exe rm -f e2cp.exe rm -f e2md.exe + rm -f mke2nod.exe diff --git a/Makefile.unix b/Makefile.unix index 538b3a0..b5028c0 100644 --- a/Makefile.unix +++ b/Makefile.unix @@ -8,7 +8,7 @@ CC := gcc CFLAGS := -D_FILE_OFFSET_BITS=64 -Wall -Werror -Wextra -std=c90 ifeq ($(OS), Windows_NT) -all: mke2fs.exe e2md.exe e2cp.exe +all: mke2fs.exe e2md.exe e2cp.exe mke2nod.exe mke2fs.exe: mke2fs.c cache.c common.c list.c report.c @@ -21,8 +21,12 @@ e2md.exe: e2md.c cache.c common.c list.c report.c e2cp.exe: e2cp.c cache.c common.c list.c report.c $(CC) $(CFLAGS) -o $@ $^ + +mke2nod.exe: mke2nod.c cache.c common.c list.c report.c + + $(CC) $(CFLAGS) -o $@ $^ else -all: mke2fs e2md e2cp +all: mke2fs e2md e2cp mke2nod mke2fs: mke2fs.c cache.c common.c list.c report.c @@ -35,6 +39,10 @@ e2md: e2md.c cache.c common.c list.c report.c e2cp: e2cp.c cache.c common.c list.c report.c $(CC) $(CFLAGS) -o $@ $^ + +mke2nod: mke2nod.c cache.c common.c list.c report.c + + $(CC) $(CFLAGS) -o $@ $^ endif clean: @@ -47,3 +55,6 @@ clean: if [ -f e2cp.exe ]; then rm -rf e2cp.exe; fi if [ -f e2cp ]; then rm -rf e2cp; fi + + if [ -f mke2nod.exe ]; then rm -rf mke2nod.exe; fi + if [ -f mke2nod ]; then rm -rf mke2nod; fi diff --git a/Makefile.w32 b/Makefile.w32 index 0f48bad..c6a75f2 100644 --- a/Makefile.w32 +++ b/Makefile.w32 @@ -7,7 +7,7 @@ VPATH := $(SRCDIR) CC := gcc CFLAGS := -D_FILE_OFFSET_BITS=64 -Wall -Werror -Wextra -std=c90 -all: mke2fs.exe e2md.exe e2cp.exe +all: mke2fs.exe e2md.exe e2cp.exe mke2nod.exe clean: @@ -20,6 +20,9 @@ clean: if exist e2cp.exe ( del /q e2cp.exe ) if exist e2cp ( del /q e2cp ) + if exist mke2nod.exe ( del /q mke2nod.exe ) + if exist mke2nod ( del /q mke2nod ) + mke2fs.exe: mke2fs.c cache.c common.c list.c report.c $(CC) $(CFLAGS) -o $@ $^ @@ -31,3 +34,7 @@ e2md.exe: e2md.c cache.c common.c list.c report.c e2cp.exe: e2cp.c cache.c common.c list.c report.c $(CC) $(CFLAGS) -o $@ $^ + +mke2nod.exe: mke2nod.c cache.c common.c list.c report.c + + $(CC) $(CFLAGS) -o $@ $^ diff --git a/common.c b/common.c index 2322812..6ab1375 100644 --- a/common.c +++ b/common.c @@ -813,7 +813,7 @@ out: #define GRP_GROUP_OF_INODE(fs, nod) \ (((nod) - 1) / byte_array_to_integer ((fs)->sb->s_inodes_per_group, 4)) -unsigned long mknod_fs (struct filesystem *fs, unsigned long parent_nod, const char *name, unsigned long mode, unsigned short uid, unsigned short gid, unsigned long ctime, unsigned long mtime) { +unsigned long mknod_fs (struct filesystem *fs, unsigned long parent_nod, const char *name, unsigned long mode, unsigned short uid, unsigned short gid, unsigned char major, unsigned char minor, unsigned long ctime, unsigned long mtime) { unsigned long nod, used_dirs_count; @@ -830,6 +830,22 @@ unsigned long mknod_fs (struct filesystem *fs, unsigned long parent_nod, const c switch (mode & FM_IFMT) { + case FM_IFBLK: case FM_IFCHR: + + if (fs->swapit) { + + node->i_block[3] = minor; + node->i_block[2] = major; + + } else { + + node->i_block[0] = minor; + node->i_block[1] = major; + + } + + break; + case FM_IFDIR: add2dir (fs, nod, nod, "."); @@ -862,7 +878,7 @@ unsigned long mknod_fs (struct filesystem *fs, unsigned long parent_nod, const c } unsigned long mkdir_fs (struct filesystem *fs, unsigned long parent_nod, const char *name, unsigned long mode, unsigned short uid, unsigned short gid, unsigned long ctime, unsigned long mtime) { - return mknod_fs (fs, parent_nod, name, mode | FM_IFDIR, uid, gid, ctime, mtime); + return mknod_fs (fs, parent_nod, name, mode | FM_IFDIR, uid, gid, 0, 0, ctime, mtime); } unsigned long rndup (unsigned long qty, unsigned long siz) { diff --git a/common.h b/common.h index 9dd806c..58e17d7 100644 --- a/common.h +++ b/common.h @@ -91,7 +91,9 @@ unsigned long rndup (unsigned long qty, unsigned long siz); #define FM_IFMT 0170000 #define FM_IFREG 0100000 +#define FM_IFBLK 0060000 #define FM_IFDIR 0040000 +#define FM_IFCHR 0020000 #define FM_IRWXU 0000700 #define FM_IRGRP 0000040 #define FM_IXGRP 0000010 @@ -155,7 +157,7 @@ struct nod_info { }; struct filesystem *alloc_fs (void); -unsigned long mknod_fs (struct filesystem *fs, unsigned long parent_nod, const char *name, unsigned long mode, unsigned short uid, unsigned short gid, unsigned long ctime, unsigned long mtime); +unsigned long mknod_fs (struct filesystem *fs, unsigned long parent_nod, const char *name, unsigned long mode, unsigned short uid, unsigned short gid, unsigned char major, unsigned char minor, unsigned long ctime, unsigned long mtime); struct group_descriptor *get_gd (struct filesystem *fs, unsigned long no, struct gd_info **rgi); void put_gd (struct gd_info *gi); diff --git a/e2cp.c b/e2cp.c index eaa6d45..2a0b458 100644 --- a/e2cp.c +++ b/e2cp.c @@ -379,7 +379,7 @@ static unsigned long mkfile_fs (struct filesystem *fs, unsigned long parent_nod, struct nod_info *ni; struct inode *node; - nod = mknod_fs (fs, parent_nod, name, mode_con (mode), uid, gid, ctime, mtime); + nod = mknod_fs (fs, parent_nod, name, mode_con (mode), uid, gid, 0, 0, ctime, mtime); node = get_nod (fs, nod, &ni); inode_pos_init (fs, &ipos, nod, INODE_POS_TRUNCATE, 0); diff --git a/e2md.c b/e2md.c index eb8e354..30db324 100644 --- a/e2md.c +++ b/e2md.c @@ -346,7 +346,7 @@ static void walk_dir (struct filesystem *fs, char *dirname) { } - mknod_fs (fs, parent_nod, p1, mode_con (mode), 0, 0, timestamp, timestamp); + mknod_fs (fs, parent_nod, p1, mode_con (mode), 0, 0, 0, 0, timestamp, timestamp); } diff --git a/mke2nod.c b/mke2nod.c new file mode 100644 index 0000000..03f31b4 --- /dev/null +++ b/mke2nod.c @@ -0,0 +1,439 @@ +/****************************************************************************** + * @file mke2nod.c + *****************************************************************************/ +#include +#include +#include +#include +#include +#include +#include + +#include "common.h" +#include "inode.h" +#include "report.h" +#include "super.h" + +static char *mode = 0; + +#define OPTION_BIGENDIAN 0x0001 +#define OPTION_INPUT 0x0002 +#define OPTION_HELP 0x0003 +#define OPTION_MODE 0x0004 +#define OPTION_OFFSET 0x0005 + +struct option { + + const char *name; + int index, flags; + +}; + +#define OPTION_NO_ARG 0x0001 +#define OPTION_HAS_ARG 0x0002 + +static struct option opts[] = { + + { "-i", OPTION_INPUT, OPTION_HAS_ARG }, + + { "--bigendian", OPTION_BIGENDIAN, OPTION_NO_ARG }, + { "--help", OPTION_HELP, OPTION_NO_ARG }, + { "--mode", OPTION_MODE, OPTION_HAS_ARG }, + { "--offset", OPTION_OFFSET, OPTION_HAS_ARG }, + + { 0, 0, 0 } + +}; + +static char **args = 0; +static long nb_args = 0; + +static int strstart (const char *val, const char **str) { + + const char *p = val; + const char *q = *str; + + while (*p != '\0') { + + if (*p != *q) { + return 0; + } + + ++p; + ++q; + + } + + *str = q; + return 1; + +} + +static void print_help (void) { + + if (program_name) { + + fprintf (stderr, "Usage: %s [options] name type major minor\n\n", program_name); + fprintf (stderr, "Options:\n\n"); + + fprintf (stderr, " Short options:\n\n"); + fprintf (stderr, " -i Specify the input target.\n"); + + fprintf (stderr, "\n"); + + fprintf (stderr, " Long options:\n\n"); + fprintf (stderr, " --help Show this help information then exit.\n"); + fprintf (stderr, " --offset SECTOR Write the filesystem starting at SECTOR.\n"); + + } + + exit (EXIT_SUCCESS); + +} + +static void dynarray_add (void *ptab, long *nb_ptr, void *data) { + + int nb, nb_alloc; + void **pp; + + nb = *nb_ptr; + pp = *(void ***) ptab; + + if ((nb & (nb - 1)) == 0) { + + if (!nb) { + nb_alloc = 1; + } else { + nb_alloc = nb * 2; + } + + pp = xrealloc (pp, nb_alloc * sizeof (void *)); + *(void ***) ptab = pp; + + } + + pp[nb++] = data; + *nb_ptr = nb; + +} + +static void parse_args (int argc, char **argv, int optind) { + + struct option *popt; + const char *optarg, *r; + + if (argc <= optind) { + print_help (); + } + + while (optind < argc) { + + r = argv[optind++]; + + if (r[0] != '-' || r[1] == '\0') { + + dynarray_add (&args, &nb_args, xstrdup (r)); + continue; + + } + + for (popt = opts; popt; popt++) { + + const char *p1 = popt->name; + const char *r1 = r; + + if (!p1) { + + report_at (program_name, 0, REPORT_ERROR, "invalid option -- '%s'", r); + exit (EXIT_FAILURE); + + } + + if (!strstart (p1, &r1)) { + continue; + } + + optarg = r1; + + if (popt->flags & OPTION_HAS_ARG) { + + if (*optarg == '\0') { + + if (optind >= argc) { + + report_at (program_name, 0, REPORT_ERROR, "argument to '%s' is missing", r); + exit (EXIT_FAILURE); + + } + + optarg = argv[optind++]; + + } + + } else if (*optarg != '\0') { + continue; + } + + break; + + } + + switch (popt->index) { + + case OPTION_BIGENDIAN: { + + bigendian = 1; + break; + + } + + case OPTION_HELP: { + + print_help (); + break; + + } + + case OPTION_INPUT: { + + if (outfile) { + + report_at (program_name, 0, REPORT_ERROR, "multiple output files provided"); + exit (EXIT_FAILURE); + + } + + outfile = xstrdup (optarg); + break; + + } + + case OPTION_MODE: { + + if (strlen (optarg) != 3) { + + report_at (program_name, 0, REPORT_ERROR, "invalid mode provided"); + exit (EXIT_FAILURE); + + } + + memcpy (mode + 3, optarg, 3); + break; + + } + + case OPTION_OFFSET: { + + long conversion; + char *temp; + + errno = 0; + conversion = strtol (optarg, &temp, 0); + + if (!*optarg || isspace ((int) *optarg) || errno || *temp) { + + report_at (program_name, 0, REPORT_ERROR, "bad number for offset (%s)", optarg); + exit (EXIT_FAILURE); + + } + + if (conversion < 0 || conversion > INT_MAX) { + + report_at (program_name, 0, REPORT_ERROR, "offset must be between 0 and %u", INT_MAX); + exit (EXIT_FAILURE); + + } + + offset = conversion; + break; + + } + + default: { + + report_at (program_name, 0, REPORT_ERROR, "unsupported option '%s'", r); + exit (EXIT_FAILURE); + + } + + } + + } + +} + +static void cleanup (void) { + + if (ofp != NULL) { + fclose (ofp); + } + +} + +static unsigned long find_entry (struct filesystem *fs, unsigned long nod, const char *name) { + + struct blockwalker bw; + unsigned long nlen, bk; + + nlen = strlen (name); + init_bw (&bw); + + while ((bk = walk_bw (fs, nod, &bw, 0, 0)) != WALK_END) { + + struct directory *d; + struct dirwalker dw; + + for (d = get_dir (fs, bk, &dw); d; d = next_dir (&dw)) { + + if (byte_array_to_integer (d->d_inode, 4) && (nlen == byte_array_to_integer (d->d_name_len, 2)) && !strncmp (dir_name (&dw), name, nlen)) { + + unsigned long result = byte_array_to_integer (d->d_inode, 4); + put_dir (&dw); + + return result; + + } + + } + + put_dir (&dw); + + } + + return 0; + +} + +static void walk_path (struct filesystem *fs, char *path, unsigned char major, unsigned char minor) { + + unsigned long parent_nod = EXT2_ROOT_INO, timestamp = time (0); + char *p1 = path, *p2, saved_ch; + + while (*p1 && (*p1 == '/' || *p1 == '\\')) { + p1++; + } + + if (*p1) { + + for (; (p2 = strchr (p1, '/')) || (p2 = strchr (p1, '\\')); p1 = p2 + 1) { + + saved_ch = *p2; + *p2 = '\0'; + + if (strlen (p1) >= 14) { + p1[13] = '\0'; + } + + if (!(parent_nod = find_entry (fs, parent_nod, p1))) { + + report_at (program_name, 0, REPORT_ERROR, "cannot access '%s'", path); + + *p2 = saved_ch; + return; + + } + + *p2 = saved_ch; + + } + + if (find_entry (fs, parent_nod, p1)) { + + report_at (program_name, 0, REPORT_ERROR, "'%s' already exists", path); + return; + + } + + } + + mknod_fs (fs, parent_nod, p1, mode_con (mode), 0, 0, major, minor, timestamp, timestamp); + +} + +int main (int argc, char **argv) { + + struct superblock sup = { 0 }; + struct filesystem *fs; + + if (argc && *argv) { + + char *p; + program_name = *argv; + + if ((p = strrchr (program_name, '/')) || (p = strrchr (program_name, '\\'))) { + program_name = (p + 1); + } + + } + + atexit (cleanup); + + mode = xstrdup ("---666"); + parse_args (argc, argv, 1); + + if (!outfile) { + + report_at (program_name, 0, REPORT_ERROR, "no input file was provided"); + return EXIT_FAILURE; + + } + + if ((ofp = fopen (outfile, "r+b")) == NULL) { + + report_at (program_name, 0, REPORT_ERROR, "faild to open '%s' for writing", outfile); + return EXIT_FAILURE; + + } + + seekto (ofp, EXT2_SUPERBLOCK_OFFSET / BLOCKSIZE); + + if (fread (&sup, sizeof (sup), 1, ofp) != 1) { + + report_at (program_name, 0, REPORT_ERROR, "failed to whilst reading '%s'", outfile); + exit (EXIT_FAILURE); + + } + + if (bigendian) { + swap_sb (&sup); + } + + if (sup.s_magic[0] != (EXT2_SUPER_MAGIC & 0xff) || sup.s_magic[1] != ((EXT2_SUPER_MAGIC >> 8) & 0xff)) { + + report_at (program_name, 0, REPORT_ERROR, "'%s' has a unsupported file system", outfile); + exit (EXIT_FAILURE); + + } + + fs = alloc_fs (); + fs->swapit = bigendian; + + fs->sb = ⊃ + + if (nb_args != 4) { + + report_at (program_name, 0, REPORT_ERROR, "invalid number of arguments passed"); + exit (EXIT_FAILURE); + + } + + switch (args[1][0]) { + + case 'b': case 'c': case 'u': case 'p': + + mode[0] = args[1][0]; + break; + + default: + + report_at (program_name, 0, REPORT_ERROR, "invalid type provided"); + exit (EXIT_FAILURE); + + } + + walk_path (fs, args[0], atoi (args[2]), atoi (args[3])); + + finish_fs (fs); + return (get_error_count () > 0) ? EXIT_FAILURE : EXIT_SUCCESS; + +}