From 22484386ee8f37d76b59f5517c2d64a8eac4189f Mon Sep 17 00:00:00 2001 From: Gregory Nutt Date: Tue, 20 Mar 2018 12:37:01 -0600 Subject: [PATCH] fs/cromfs and tools/gencromfs: Various fixes for traversal relative file paths. Biggest changes is in types used: Cannot use size_t or mode_t in common structures because they have different sizes on the (64-bit) host and the (32-bit) target. Use uint32_t instead of size_t for offsets. Use uint16_t instead of mode_t. --- fs/cromfs/cromfs.h | 36 ++++++++----- fs/cromfs/fs_cromfs.c | 31 +++++------ include/nuttx/fs/dirent.h | 4 +- include/sys/types.h | 14 ++--- tools/gencromfs.c | 106 ++++++++++++++++++++++---------------- 5 files changed, 109 insertions(+), 82 deletions(-) diff --git a/fs/cromfs/cromfs.h b/fs/cromfs/cromfs.h index b9c61477ed..f94f64b21c 100644 --- a/fs/cromfs/cromfs.h +++ b/fs/cromfs/cromfs.h @@ -47,6 +47,17 @@ * Public Types ****************************************************************************/ +/* Maximum size of an offset. This should normally be size_t since this is + * an in-memory file system. However, uint32_t is 32-bits on most 32-bit + * target machines but 64-bits on 64-host machines. We restrict offsets to + * 32-bits for commonality (limiting the size of the CROMFS image to 4Gb). + * + * REVISIT: What about small memory systems where the size_t is only 16-bits? + * + * Similarly, the NuttX mode_t is only 16-bits so uint16_t is explicitly used + * for NuttX file modes. + */ + /* This structure describes the CROMFS volume. It provides most of the * information needed for statfs() including: * @@ -70,10 +81,7 @@ * * The volume header is followed immediately by the root directory node. An * offset to that node is used to permit future variable length data (such as - * a volumne name) which may intervene. - * - * Since this is an in-memory file system, size_t is the most relevant type for - * internal file system offsets. + * a volume name) which may intervene. */ struct cromfs_volume_s @@ -81,9 +89,9 @@ struct cromfs_volume_s uint32_t cv_magic; /* Must be first. Must be CROMFS_MAGIC */ uint16_t cv_nnodes; /* Total number of nodes in-use */ uint16_t cv_nblocks; /* Total number of data blocks in-use */ - size_t cv_root; /* Offset to the first node in the root file system */ - size_t cv_fsize; /* Size of the compressed file system image */ - size_t cv_bsize; /* Optimal block size for transfers */ + uint32_t cv_root; /* Offset to the first node in the root file system */ + uint32_t cv_fsize; /* Size of the compressed file system image */ + uint32_t cv_bsize; /* Optimal block size for transfers */ }; /* This describes one node in the CROMFS file system. It holds node meta @@ -111,16 +119,16 @@ struct cromfs_volume_s struct cromfs_node_s { - mode_t cn_mode; /* File type, attributes, and access mode bits */ - size_t cn_name; /* Offset from the beginning of the volume header to the + uint16_t cn_mode; /* File type, attributes, and access mode bits */ + uint32_t cn_name; /* Offset from the beginning of the volume header to the * node name string. NUL-terminated. */ - size_t cn_size; /* Size of the uncompressed data (in bytes) */ - size_t cn_peer; /* Offset to next node in this directory (for readdir()) */ + uint32_t cn_size; /* Size of the uncompressed data (in bytes) */ + uint32_t cn_peer; /* Offset to next node in this directory (for readdir()) */ union { - size_t cn_child; /* Offset to first node in sub-directory (directories only) */ - size_t cn_link; /* Offset to an arbitrary node (for hard link) */ - size_t cn_blocks; /* Offset to first block of compressed data (for read) */ + uint32_t cn_child; /* Offset to first node in sub-directory (directories only) */ + uint32_t cn_link; /* Offset to an arbitrary node (for hard link) */ + uint32_t cn_blocks; /* Offset to first block of compressed data (for read) */ } u; }; diff --git a/fs/cromfs/fs_cromfs.c b/fs/cromfs/fs_cromfs.c index 11921807c5..ce4809f1f7 100644 --- a/fs/cromfs/fs_cromfs.c +++ b/fs/cromfs/fs_cromfs.c @@ -100,8 +100,8 @@ struct cromfs_comparenode_s /* Helpers */ static FAR void *cromfs_offset2addr(FAR const struct cromfs_volume_s *fs, - size_t offset); -static size_t cromfs_addr2offset(FAR const struct cromfs_volume_s *fs, + uint32_t offset); +static uint32_t cromfs_addr2offset(FAR const struct cromfs_volume_s *fs, FAR const void *addr); static int cromfs_foreach_node(FAR const struct cromfs_volume_s *fs, cromfs_foreach_t callback, FAR void *arg); @@ -200,7 +200,7 @@ extern const struct cromfs_volume_s g_cromfs_image; ****************************************************************************/ static FAR void *cromfs_offset2addr(FAR const struct cromfs_volume_s *fs, - size_t offset) + uint32_t offset) { /* Zero offset is a specials case: It corresponds to a NULL address */ @@ -222,12 +222,12 @@ static FAR void *cromfs_offset2addr(FAR const struct cromfs_volume_s *fs, * Name: cromfs_offset2addr ****************************************************************************/ -static size_t cromfs_addr2offset(FAR const struct cromfs_volume_s *fs, - FAR const void *addr) +static uint32_t cromfs_addr2offset(FAR const struct cromfs_volume_s *fs, + FAR const void *addr) { uintptr_t start; uintptr_t target; - size_t offset; + uint32_t offset; /* NULL is a specials case: It corresponds to offset zero */ @@ -346,7 +346,8 @@ static int cromfs_comparenode(FAR const struct cromfs_volume_s *fs, * and return 1 to stop the traversal. */ - *cpnode->node = node; + *cpnode->node = (FAR const struct cromfs_node_s *) + cromfs_offset2addr(fs, node->u.cn_child); return 1; } @@ -574,7 +575,7 @@ static ssize_t cromfs_read(FAR struct file *filep, FAR char *buffer, FAR const uint8_t *src; off_t fpos; size_t remaining; - size_t blkoffs; + uint32_t blkoffs; uint16_t ulen; uint16_t clen; unsigned int copysize; @@ -638,7 +639,7 @@ static ssize_t cromfs_read(FAR struct file *filep, FAR char *buffer, do { - size_t blksize; + uint32_t blksize; /* Go to the next block */ @@ -652,7 +653,7 @@ static ssize_t cromfs_read(FAR struct file *filep, FAR char *buffer, ulen = (uint16_t)hdr0->lzf_len[0] << 8 | (uint16_t)hdr0->lzf_len[1]; - blksize = (size_t)ulen + LZF_TYPE0_HDR_SIZE; + blksize = (uint32_t)ulen + LZF_TYPE0_HDR_SIZE; } else { @@ -663,7 +664,7 @@ static ssize_t cromfs_read(FAR struct file *filep, FAR char *buffer, (uint16_t)hdr1->lzf_ulen[1]; clen = (uint16_t)hdr1->lzf_clen[0] << 8 | (uint16_t)hdr1->lzf_clen[1]; - blksize = (size_t)clen + LZF_TYPE1_HDR_SIZE; + blksize = (uint32_t)clen + LZF_TYPE1_HDR_SIZE; } nexthdr = (FAR struct lzf_header_s *)((FAR uint8_t *)currhdr + blksize); @@ -836,8 +837,8 @@ static int cromfs_fstat(FAR const struct file *filep, FAR struct stat *buf) FAR struct inode *inode; FAR struct cromfs_volume_s *fs; FAR struct cromfs_file_s *ff; - size_t fsize; - size_t bsize; + uint32_t fsize; + uint32_t bsize; /* Sanity checks */ @@ -916,7 +917,7 @@ static int cromfs_opendir(FAR struct inode *mountpt, FAR const char *relpath, /* Set the start node and next node to the first entry in the directory */ - dir->u.cromfs.cr_firstoffset = (size_t)cromfs_addr2offset(fs, node); + dir->u.cromfs.cr_firstoffset = cromfs_addr2offset(fs, node); dir->u.cromfs.cr_curroffset = dir->u.cromfs.cr_firstoffset; return OK; } @@ -933,7 +934,7 @@ static int cromfs_readdir(struct inode *mountpt, struct fs_dirent_s *dir) FAR const struct cromfs_volume_s *fs; FAR const struct cromfs_node_s *node; FAR char *name; - size_t offset; + uint32_t offset; finfo("mountpt: %p dir: %p\n", mountpt, dir); diff --git a/include/nuttx/fs/dirent.h b/include/nuttx/fs/dirent.h index ec371ea836..278f8c74f8 100644 --- a/include/nuttx/fs/dirent.h +++ b/include/nuttx/fs/dirent.h @@ -108,8 +108,8 @@ struct fs_romfsdir_s struct fs_cromfsdir_s { - off_t cr_firstoffset; /* Offset to the first entry in the directory */ - off_t cr_curroffset; /* Current offset into the directory contents */ + uint32_t cr_firstoffset; /* Offset to the first entry in the directory */ + uint32_t cr_curroffset; /* Current offset into the directory contents */ }; #endif /* CONFIG_FS_CROMFS */ diff --git a/include/sys/types.h b/include/sys/types.h index 321be8d9d9..64dd844e70 100644 --- a/include/sys/types.h +++ b/include/sys/types.h @@ -111,20 +111,20 @@ /* Floating point types */ -typedef float float32; +typedef float float32; #ifndef CONFIG_HAVE_DOUBLE -typedef float double_t; -typedef float float64; +typedef float double_t; +typedef float float64; #else -typedef double double_t; -typedef double float64; +typedef double double_t; +typedef double float64; #endif /* Misc. scalar types */ /* mode_t is an integer type used for file attributes. mode_t needs - * to be at least 16-bits but, in fact must be sizeof(int) because it is - * pased via varargs. + * to be at least 16-bits but, in fact, must be sizeof(int) because it is + * passed via varargs. */ typedef unsigned int mode_t; diff --git a/tools/gencromfs.c b/tools/gencromfs.c index 8f3c378ab3..d69b07cf9a 100644 --- a/tools/gencromfs.c +++ b/tools/gencromfs.c @@ -4,6 +4,14 @@ * Copyright (C) 2018 Gregory Nutt. All rights reserved. * Author: Gregory Nutt * + * The function lzf_compress() comes from the file lzf_c.c (wich substantial + * modification): + * + * Copyright (c) 2000-2010 Marc Alexander Lehmann + * + * Which has a compatible BSD license and included here under the NuttX BSD + * license: + * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: @@ -114,54 +122,63 @@ * Private Types ****************************************************************************/ +/* Maximum size of an offset. This should normally be size_t since this is + * an in-memory file system. However, size_t is 32-bits on most 32-bit + * target machines but 64-bits on 64-host machines. We restrict offsets to + * 32-bits for commonality (limiting the size of the CROMFS image to 4Gb) + * + * Similarly, the NuttX mode_t is only 16-bits so uint16_t is explicitly used + * for NuttX file modes. + */ + /* CROMFS structures */ struct cromfs_volume_s { - uint32_t cv_magic; /* Must be first. Must be CROMFS_MAGIC */ - uint16_t cv_nnodes; /* Total number of nodes in-use */ - uint16_t cv_nblocks; /* Total number of data blocks in-use */ - size_t cv_root; /* Offset to the first node in the root file system */ - size_t cv_fsize; /* Size of the compressed file system image */ - size_t cv_bsize; /* Optimal block size for transfers */ + uint32_t cv_magic; /* Must be first. Must be CROMFS_MAGIC */ + uint16_t cv_nnodes; /* Total number of nodes in-use */ + uint16_t cv_nblocks; /* Total number of data blocks in-use */ + uint32_t cv_root; /* Offset to the first node in the root file system */ + uint32_t cv_fsize; /* Size of the compressed file system image */ + uint32_t cv_bsize; /* Optimal block size for transfers */ }; struct cromfs_node_s { - mode_t cn_mode; /* File type, attributes, and access mode bits */ - size_t cn_name; /* Offset from the beginning of the volume header to the - * node name string. NUL-terminated. */ - size_t cn_size; /* Size of the uncompressed data (in bytes) */ - size_t cn_peer; /* Offset to next node in this directory (for readdir()) */ + uint16_t cn_mode; /* File type, attributes, and access mode bits */ + uint32_t cn_name; /* Offset from the beginning of the volume header to the + * node name string. NUL-terminated. */ + uint32_t cn_size; /* Size of the uncompressed data (in bytes) */ + uint32_t cn_peer; /* Offset to next node in this directory (for readdir()) */ union { - size_t cn_child; /* Offset to first node in sub-directory (directories only) */ - size_t cn_link; /* Offset to an arbitrary node (for hard link) */ - size_t cn_blocks; /* Offset to first block of compressed data (for read) */ + uint32_t cn_child; /* Offset to first node in sub-directory (directories only) */ + uint32_t cn_link; /* Offset to an arbitrary node (for hard link) */ + uint32_t cn_blocks; /* Offset to first block of compressed data (for read) */ } u; }; /* LZF headers */ -struct lzf_header_s /* Common data header */ +struct lzf_header_s /* Common data header */ { - uint8_t lzf_magic[2]; /* [0]='Z', [1]='V' */ - uint8_t lzf_type; /* LZF_TYPE0_HDR or LZF_TYPE1_HDR */ + uint8_t lzf_magic[2]; /* [0]='Z', [1]='V' */ + uint8_t lzf_type; /* LZF_TYPE0_HDR or LZF_TYPE1_HDR */ }; -struct lzf_type0_header_s /* Uncompressed data header */ +struct lzf_type0_header_s /* Uncompressed data header */ { - uint8_t lzf_magic[2]; /* [0]='Z', [1]='V' */ - uint8_t lzf_type; /* LZF_TYPE0_HDR */ - uint8_t lzf_len[2]; /* Data length (big-endian) */ + uint8_t lzf_magic[2]; /* [0]='Z', [1]='V' */ + uint8_t lzf_type; /* LZF_TYPE0_HDR */ + uint8_t lzf_len[2]; /* Data length (big-endian) */ }; -struct lzf_type1_header_s /* Compressed data header */ +struct lzf_type1_header_s /* Compressed data header */ { - uint8_t lzf_magic[2]; /* [0]='Z', [1]='V' */ - uint8_t lzf_type; /* LZF_TYPE1_HDR */ - uint8_t lzf_clen[2]; /* Compressed data length (big-endian) */ - uint8_t lzf_ulen[2]; /* Uncompressed data length (big-endian) */ + uint8_t lzf_magic[2]; /* [0]='Z', [1]='V' */ + uint8_t lzf_type; /* LZF_TYPE1_HDR */ + uint8_t lzf_clen[2]; /* Compressed data length (big-endian) */ + uint8_t lzf_ulen[2]; /* Uncompressed data length (big-endian) */ }; /* LZF data buffer */ @@ -209,9 +226,9 @@ static const char g_delim[] = "*************************************************************************" "***********************"; -static size_t g_offset; /* Current image offset */ -static size_t g_diroffset; /* Offset for '.' */ -static size_t g_parent_offset; /* Offset for '..' */ +static uint32_t g_offset; /* Current image offset */ +static uint32_t g_diroffset; /* Offset for '.' */ +static uint32_t g_parent_offset; /* Offset for '..' */ static unsigned int g_nnodes; /* Number of nodes generated */ static unsigned int g_nblocks; /* Number of blocks of data generated */ @@ -237,8 +254,8 @@ static void dump_hexbuffer(FILE *stream, const void *buffer, unsigned int nbytes static void dump_nextline(FILE *stream); static size_t lzf_compress(const uint8_t *inbuffer, unsigned int inlen, union lzf_result_u *result); -static mode_t get_mode(mode_t mode); -static void gen_dirlink(const char *name, size_t tgtoffs); +static uint16_t get_mode(mode_t mode); +static void gen_dirlink(const char *name, uint32_t tgtoffs); static void gen_directory(const char *path, const char *name, mode_t mode, bool lastentry); static void gen_file(const char *path, const char *name, mode_t mode, @@ -789,9 +806,9 @@ genhdr: return retlen; } -static mode_t get_mode(mode_t mode) +static uint16_t get_mode(mode_t mode) { - mode_t ret = 0; + uint16_t ret = 0; if ((mode & S_IXOTH) != 0) { @@ -841,7 +858,7 @@ static mode_t get_mode(mode_t mode) return ret; } -static void gen_dirlink(const char *name, size_t tgtoffs) +static void gen_dirlink(const char *name, uint32_t tgtoffs) { struct cromfs_node_s node; int namlen; @@ -850,6 +867,7 @@ static void gen_dirlink(const char *name, size_t tgtoffs) /* Generate the hardlink node */ + dump_nextline(g_tmpstream); fprintf(g_tmpstream, "\n /* Offset %6lu: Hard link %s*/\n\n", (unsigned long)g_offset, name); @@ -863,7 +881,6 @@ static void gen_dirlink(const char *name, size_t tgtoffs) node.cn_peer = g_offset; node.u.cn_link = tgtoffs; - dump_nextline(g_tmpstream); dump_hexbuffer(g_tmpstream, &node, sizeof(struct cromfs_node_s)); dump_hexbuffer(g_tmpstream, name, namlen); @@ -874,9 +891,9 @@ static void gen_directory(const char *path, const char *name, mode_t mode, bool lastentry) { struct cromfs_node_s node; - size_t save_offset = g_offset; - size_t save_diroffset = g_diroffset; - size_t save_parent_offset = g_parent_offset; + uint32_t save_offset = g_offset; + uint32_t save_diroffset = g_diroffset; + uint32_t save_parent_offset = g_parent_offset; FILE *save_tmpstream = g_tmpstream; FILE *subtree_stream; int namlen; @@ -921,6 +938,10 @@ static void gen_directory(const char *path, const char *name, mode_t mode, /* Generate the directory node */ + dump_nextline(g_tmpstream); + fprintf(g_tmpstream, "\n /* Offset %6lu: Directory %s */\n\n", + (unsigned long)save_offset, path); + node.cn_mode = (NUTTX_IFDIR | get_mode(mode)); save_offset += sizeof(struct cromfs_node_s); @@ -931,9 +952,6 @@ static void gen_directory(const char *path, const char *name, mode_t mode, node.cn_peer = lastentry ? 0 : g_offset; node.u.cn_child = save_offset; - fprintf(g_tmpstream, "\n /* Offset %6lu: Directory %s */\n\n", - (unsigned long)save_offset, path); - dump_nextline(g_tmpstream); dump_hexbuffer(g_tmpstream, &node, sizeof(struct cromfs_node_s)); dump_hexbuffer(g_tmpstream, name, namlen); @@ -949,7 +967,7 @@ static void gen_file(const char *path, const char *name, mode_t mode, { struct cromfs_node_s node; union lzf_result_u result; - size_t nodeoffs = g_offset; + uint32_t nodeoffs = g_offset; FILE *save_tmpstream = g_tmpstream; FILE *outstream; FILE *instream; @@ -1033,9 +1051,9 @@ static void gen_file(const char *path, const char *name, mode_t mode, dump_nextline(g_tmpstream); - fprintf(g_tmpstream, "\n /* Offset %6lu: File %s/%s: " + fprintf(g_tmpstream, "\n /* Offset %6lu: File %s: " "Uncompressed=%lu Compressed=%lu */\n\n", - (unsigned long)nodeoffs, path, name, (unsigned long)ntotal, + (unsigned long)nodeoffs, path, (unsigned long)ntotal, (unsigned long)blktotal); node.cn_mode = (NUTTX_IFREG | get_mode(mode));