From 3ec02adee00a86de0f3375cd7728338cf1a134bf Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Wed, 21 Mar 2018 08:40:02 -0600 Subject: [PATCH] tools/genromfs.c: Improve check for empty directories. If the directory contains only unsupported, special files, then it is still empty. Fix some collection of statistics that was cause statfs() to return some incorrect values. Add logic to handle the case where the host and the target differ in endian-ness. fs/procfs: In show mountpoints, add support so that the CROMFS file system type is recognized. --- fs/mount/fs_gettype.c | 8 +++- tools/Makefile.host | 6 +++ tools/gencromfs.c | 109 +++++++++++++++++++++++++++++++++--------- 3 files changed, 99 insertions(+), 24 deletions(-) diff --git a/fs/mount/fs_gettype.c b/fs/mount/fs_gettype.c index 4c97c9d75b..971a8b46d4 100644 --- a/fs/mount/fs_gettype.c +++ b/fs/mount/fs_gettype.c @@ -1,7 +1,7 @@ /**************************************************************************** * fs/mount/fs_mount.c * - * Copyright (C) 2017 Gregory Nutt. All rights reserved. + * Copyright (C) 2017-2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * * Redistribution and use in source and binary forms, with or without @@ -84,6 +84,12 @@ FAR const char *fs_gettype(FAR struct statfs *statbuf) break; #endif +#ifdef CONFIG_FS_CROMFS + case CROMFS_MAGIC: + fstype = "cromfs"; + break; +#endif + #ifdef CONFIG_FS_TMPFS case TMPFS_MAGIC: fstype = "tmpfs"; diff --git a/tools/Makefile.host b/tools/Makefile.host index 50634297d1..475ddb5392 100644 --- a/tools/Makefile.host +++ b/tools/Makefile.host @@ -38,6 +38,8 @@ TOPDIR ?= ${shell pwd}/.. -include $(TOPDIR)/Make.defs include ${TOPDIR}/tools/Config.mk +# Check the endian-ness of the target + # Define HOSTCC on the make command line if it differs from these defaults # Define HOSTCFLAGS with -g on the make command line to build debug versions @@ -66,6 +68,10 @@ HOSTEXEEXT ?= .exe endif endif +ifeq ($(CONFIG_ENDIAN_BIG),y) +CFLAGS += -DTGT_BIGENDIAN=1 +endif + # Targets all: b16$(HOSTEXEEXT) bdf-converter$(HOSTEXEEXT) cmpconfig$(HOSTEXEEXT) \ diff --git a/tools/gencromfs.c b/tools/gencromfs.c index bdd6b1a1bd..5781b727ff 100644 --- a/tools/gencromfs.c +++ b/tools/gencromfs.c @@ -59,6 +59,20 @@ * Pre-processor Definitions ****************************************************************************/ +/* HOST_BIGENDIAN or TGT_BIGENDIAN may be defined on the command line to + * adapt to different host/target combinations. Otherwise, both are assumed + * to be the same endian-ness. + */ + +#undef HOST_TGTSWAP + +#if (defined(HOST_BIGENDIAN) && !defined(TGT_BIGENDIAN)) || \ + (!defined(HOST_BIGENDIAN) && defined(TGT_BIGENDIAN)) +# define HOST_TGTSWAP 1 +#endif + +/* mkstemp() has been giving me errors on Cygwin */ + #undef USE_MKSTEMP #define TMP_NAMLEN 32 /* Actually only 22 */ @@ -260,6 +274,15 @@ static void dump_nextline(FILE *stream); static size_t lzf_compress(const uint8_t *inbuffer, unsigned int inlen, union lzf_result_u *result); static uint16_t get_mode(mode_t mode); +#ifdef HOST_TGTSWAP +static inline uint16_t tgt_uint16(uint16_t a); +static inline uint32_t tgt_uint32(uint32_t a); +# define TGT_UINT16(a) tgt_uint16(a) +# define TGT_UINT32(a) tgt_uint32(a) +#else +# define TGT_UINT16(a) (a) +# define TGT_UINT32(a) (a) +#endif static void gen_dirlink(const char *name, uint32_t tgtoffs, bool dirempty); static void gen_directory(const char *path, const char *name, mode_t mode, bool lastentry); @@ -866,6 +889,23 @@ static uint16_t get_mode(mode_t mode) return ret; } +#ifdef HOST_TGTSWAP +static inline uint16_t tgt_uint16(uint16_t a) +{ + /* [15:8][7:0] -> [7:0][15:8] */ + + return (a >> 8) | (a << 8); +} + +static inline uint32_t tgt_uint32(uint32_t a) +{ + /* [31:24][23:16][15:8][7:0] -> [7:0][15:8][23:16][31:24] */ + + return (a >> 24) | ((a >> 8) & 0x0000ff00) | + ((a << 8) & 0x00ff0000) | (a << 24); +} +#endif + static void gen_dirlink(const char *name, uint32_t tgtoffs, bool dirempty) { struct cromfs_node_s node; @@ -879,15 +919,15 @@ static void gen_dirlink(const char *name, uint32_t tgtoffs, bool dirempty) fprintf(g_tmpstream, "\n /* Offset %6lu: Hard link %s*/\n\n", (unsigned long)g_offset, name); - node.cn_mode = DIRLINK_MODEFLAGS; + node.cn_mode = TGT_UINT16(DIRLINK_MODEFLAGS); g_offset += sizeof(struct cromfs_node_s); - node.cn_name = g_offset; + node.cn_name = TGT_UINT32(g_offset); node.cn_size = 0; g_offset += namlen; - node.cn_peer = dirempty ? 0 : g_offset; - node.u.cn_link = tgtoffs; + node.cn_peer = TGT_UINT32(dirempty ? 0 : g_offset); + node.u.cn_link = TGT_UINT32(tgtoffs); dump_hexbuffer(g_tmpstream, &node, sizeof(struct cromfs_node_s)); dump_hexbuffer(g_tmpstream, name, namlen); @@ -961,15 +1001,15 @@ static void gen_directory(const char *path, const char *name, mode_t mode, fprintf(g_tmpstream, "\n /* Offset %6lu: Directory %s */\n\n", (unsigned long)save_offset, path); - node.cn_mode = (NUTTX_IFDIR | get_mode(mode)); + node.cn_mode = TGT_UINT16(NUTTX_IFDIR | get_mode(mode)); save_offset += sizeof(struct cromfs_node_s); - node.cn_name = save_offset; + node.cn_name = TGT_UINT32(save_offset); node.cn_size = 0; save_offset += namlen; - node.cn_peer = lastentry ? 0 : g_offset; - node.u.cn_child = save_offset; + node.cn_peer = TGT_UINT32(lastentry ? 0 : g_offset); + node.u.cn_child = TGT_UINT32(save_offset); dump_hexbuffer(g_tmpstream, &node, sizeof(struct cromfs_node_s)); dump_hexbuffer(g_tmpstream, name, namlen); @@ -1057,6 +1097,8 @@ static void gen_file(const char *path, const char *name, mode_t mode, ntotal += nread; blktotal += blklen; g_offset += blklen; + + g_nblocks++; blkno++; } } @@ -1075,18 +1117,18 @@ static void gen_file(const char *path, const char *name, mode_t mode, (unsigned long)nodeoffs, path, (unsigned long)ntotal, (unsigned long)blktotal); - node.cn_mode = (NUTTX_IFREG | get_mode(mode)); + node.cn_mode = TGT_UINT16(NUTTX_IFREG | get_mode(mode)); nodeoffs += sizeof(struct cromfs_node_s); - node.cn_name = nodeoffs; + node.cn_name = TGT_UINT32(nodeoffs); - node.cn_size = ntotal; + node.cn_size = TGT_UINT32(ntotal); nodeoffs += namlen; - node.u.cn_blocks = nodeoffs; + node.u.cn_blocks = TGT_UINT32(nodeoffs); nodeoffs += blktotal; - node.cn_peer = lastentry ? 0 : nodeoffs; + node.cn_peer = TGT_UINT32(lastentry ? 0 : nodeoffs); dump_hexbuffer(g_tmpstream, &node, sizeof(struct cromfs_node_s)); dump_hexbuffer(g_tmpstream, name, namlen); @@ -1098,12 +1140,33 @@ static void gen_file(const char *path, const char *name, mode_t mode, append_tmpfile(g_tmpstream, outstream); } -static int dir_notempty(const char *dirpath, const char *name, - void *arg, bool lastentry) +static int dir_notempty(const char *dirpath, const char *name, + void *arg, bool lastentry) { - /* If we get here, then the directory is not empty */ + struct stat buf; + char *path; + int ret; - return 1; + asprintf(&path, "%s/%s", dirpath, name); + + /* stat() should not fail for any reason */ + + ret = stat(path, &buf); + if (ret < 0) + { + int errcode = errno; + fprintf(stderr, "ERROR: stat(%s) failed: %s\n", + path, strerror(errcode)); + exit(1); + } + + /* The directory is not empty if it contains with a file or a directory + * entry. Anything else will be ignored and the directly may be + * effectively empty. + */ + + free(path); + return (S_ISREG(buf.st_mode) || S_ISDIR(buf.st_mode)); } static int process_direntry(const char *dirpath, const char *name, @@ -1276,12 +1339,12 @@ int main(int argc, char **argv, char **envp) fprintf(g_outstream, "{\n"); fprintf(g_outstream, "\n /* Offset %6lu: Volume header */\n\n", 0ul); - vol.cv_magic = CROMFS_MAGIC; - vol.cv_nnodes = g_nnodes; - vol.cv_nblocks = g_nblocks; - vol.cv_root = sizeof(struct cromfs_volume_s); - vol.cv_fsize = g_offset; - vol.cv_bsize = CROMFS_BLOCKSIZE; + vol.cv_magic = TGT_UINT32(CROMFS_MAGIC); + vol.cv_nnodes = TGT_UINT16(g_nnodes); + vol.cv_nblocks = TGT_UINT16(g_nblocks); + vol.cv_root = TGT_UINT32(sizeof(struct cromfs_volume_s)); + vol.cv_fsize = TGT_UINT32(g_offset); + vol.cv_bsize = TGT_UINT32(CROMFS_BLOCKSIZE); g_nhex = 0; dump_hexbuffer(g_outstream, &vol, sizeof(struct cromfs_volume_s));