FreeCalypso > hg > freecalypso-tools
view ffstools/tiffs-mkfs/input.c @ 921:74d284add54d
fc-fsio: guard against bogus readdir results from the target
If the FFS being operated on contains SE K2x0 extended filenames,
readdir will return strings that are bad for printing. We need to
guard against this possibility, and also against possible other
bogosity that could be sent by other alien firmwares.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Sat, 31 Dec 2022 22:55:23 +0000 |
parents | 12ae93940467 |
children |
line wrap: on
line source
#include <sys/types.h> #include <sys/param.h> #include <sys/stat.h> #include <dirent.h> #include <stdio.h> #include <stdint.h> #include <stdlib.h> #include <string.h> #include <strings.h> #include <unistd.h> #include "struct.h" #include "globals.h" void read_dir_level(dto, srcpath, depth) struct tree_object *dto; char *srcpath; { DIR *rdd; struct dirent *dirent; char hostpath_child[MAXPATHLEN]; struct stat hst; struct tree_object *cto; unsigned nchildren; dto->is_dir = 1; rdd = opendir(srcpath); if (!rdd) { perror(srcpath); exit(1); } nchildren = 0; while (dirent = readdir(rdd)) { if (dirent->d_name[0] == '.') continue; if (strlen(dirent->d_name) > MAX_FN_COMPONENT) { fprintf(stderr, "error: \"%s\" in %s exceeds the FFS component name limit\n", dirent->d_name, srcpath); exit(1); } if (nchildren >= MAX_DIR_ENTRIES) { fprintf(stderr, "error: %s has too many children\n", srcpath); exit(1); } cto = malloc(sizeof(struct tree_object)); if (!cto) { perror("malloc of struct tree_object"); exit(1); } strcpy(cto->name, dirent->d_name); dto->u.d.children[nchildren++] = cto; if (strlen(srcpath) + strlen(dirent->d_name) + 2 > sizeof hostpath_child) { fprintf(stderr, "error: host side pathname buffer overflow\n"); exit(1); } sprintf(hostpath_child, "%s/%s", srcpath, dirent->d_name); if (lstat(hostpath_child, &hst) < 0) { perror(hostpath_child); exit(1); } switch (hst.st_mode & S_IFMT) { case S_IFREG: cto->is_dir = 0; strcpy(cto->u.f.host_pathname, hostpath_child); break; case S_IFDIR: if (depth >= MAX_DIR_NEST-1) { fprintf(stderr, "error: directory nesting too deep at %s\n", hostpath_child); exit(1); } read_dir_level(cto, hostpath_child, depth + 1); break; default: fprintf(stderr, "error: %s is neither a regular file nor a directory\n", hostpath_child); exit(1); } } closedir(rdd); dto->u.d.nchildren = nchildren; } static int compare_func(p1, p2) struct tree_object **p1, **p2; { return strcmp((*p1)->name, (*p2)->name); } void sort_dir_level(dto) struct tree_object *dto; { unsigned n; struct tree_object *cto; if (dto->u.d.nchildren > 1) qsort(dto->u.d.children, dto->u.d.nchildren, sizeof(struct tree_object *), compare_func); for (n = 0; n < dto->u.d.nchildren; n++) { cto = dto->u.d.children[n]; if (cto->is_dir) sort_dir_level(cto); } }