view ffstools/tiffs-mkfs/input.c @ 901:2e6764022292

fc-shell tch record: add support for new TCH DL format
author Mychaela Falconia <falcon@freecalypso.org>
date Tue, 13 Dec 2022 03:24:36 +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);
	}
}