aboutsummaryrefslogtreecommitdiff
path: root/jffs2reader.c
diff options
context:
space:
mode:
authorDongsheng Yang <yangds.fnst@cn.fujitsu.com>2015-10-31 11:12:01 +0800
committerBrian Norris <computersforpeace@gmail.com>2015-11-11 14:38:40 -0800
commit7d81790ced345585b1e647ca9d0f6678e7062fa4 (patch)
tree02f61270c7a0fff7bb6b2e28f247a3d2fd6ff490 /jffs2reader.c
parent344753f2aacb94d98ce238f81fc4a4b6ef6adea9 (diff)
mtd-utils: Restructure the mtd-utils source.
* There is no code modification in this commit, only moving * the files to proper place. The user tools looks a little messy as we place almost the all tools in the root directory of mtd-utils. To make it more clear, I propose to introduce the following structure for our source code. mtd-utils/ |-- lib |-- include |-- misc-utils |-- jffsX-utils |-- nand-utils |-- nor-utils |-- ubi-utils |-- ubifs-utils `-- tests Signed-off-by: Dongsheng Yang <yangds.fnst@cn.fujitsu.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Diffstat (limited to 'jffs2reader.c')
-rw-r--r--jffs2reader.c918
1 files changed, 0 insertions, 918 deletions
diff --git a/jffs2reader.c b/jffs2reader.c
deleted file mode 100644
index a62da9a..0000000
--- a/jffs2reader.c
+++ /dev/null
@@ -1,918 +0,0 @@
-/* vi: set sw=4 ts=4: */
-/*
- * jffs2reader v0.0.18 A jffs2 image reader
- *
- * Copyright (c) 2001 Jari Kirma <Jari.Kirma@hut.fi>
- *
- * This software is provided 'as-is', without any express or implied
- * warranty. In no event will the author be held liable for any damages
- * arising from the use of this software.
- *
- * Permission is granted to anyone to use this software for any
- * purpose, including commercial applications, and to alter it and
- * redistribute it freely, subject to the following restrictions:
- *
- * 1. The origin of this software must not be misrepresented; you must
- * not claim that you wrote the original software. If you use this
- * software in a product, an acknowledgment in the product
- * documentation would be appreciated but is not required.
- *
- * 2. Altered source versions must be plainly marked as such, and must
- * not be misrepresented as being the original software.
- *
- * 3. This notice may not be removed or altered from any source
- * distribution.
- *
- *
- *********
- * This code was altered September 2001
- * Changes are Copyright (c) Erik Andersen <andersen@codepoet.org>
- *
- * In compliance with (2) above, this is hereby marked as an altered
- * version of this software. It has been altered as follows:
- * *) Listing a directory now mimics the behavior of 'ls -l'
- * *) Support for recursive listing has been added
- * *) Without options, does a recursive 'ls' on the whole filesystem
- * *) option parsing now uses getopt()
- * *) Now uses printf, and error messages go to stderr.
- * *) The copyright notice has been cleaned up and reformatted
- * *) The code has been reformatted
- * *) Several twisty code paths have been fixed so I can understand them.
- * -Erik, 1 September 2001
- *
- * *) Made it show major/minor numbers for device nodes
- * *) Made it show symlink targets
- * -Erik, 13 September 2001
- */
-
-
-/*
-TODO:
-
-- Add CRC checking code to places marked with XXX.
-- Add support for other node compression types.
-
-- Test with real life images.
-- Maybe port into bootloader.
- */
-
-/*
-BUGS:
-
-- Doesn't check CRC checksums.
- */
-
-#define PROGRAM_NAME "jffs2reader"
-
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <time.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <dirent.h>
-#include <zlib.h>
-
-#include "mtd/jffs2-user.h"
-#include "common.h"
-
-#define SCRATCH_SIZE (5*1024*1024)
-
-/* macro to avoid "lvalue required as left operand of assignment" error */
-#define ADD_BYTES(p, n) ((p) = (typeof(p))((char *)(p) + (n)))
-
-#define DIRENT_INO(dirent) ((dirent) !=NULL ? je32_to_cpu((dirent)->ino) : 0)
-#define DIRENT_PINO(dirent) ((dirent) !=NULL ? je32_to_cpu((dirent)->pino) : 0)
-
-struct dir {
- struct dir *next;
- uint8_t type;
- uint8_t nsize;
- uint32_t ino;
- char name[256];
-};
-
-int target_endian = __BYTE_ORDER;
-
-void putblock(char *, size_t, size_t *, struct jffs2_raw_inode *);
-struct dir *putdir(struct dir *, struct jffs2_raw_dirent *);
-void printdir(char *o, size_t size, struct dir *d, const char *path,
- int recurse, int want_ctime);
-void freedir(struct dir *);
-
-struct jffs2_raw_inode *find_raw_inode(char *o, size_t size, uint32_t ino);
-struct jffs2_raw_dirent *resolvedirent(char *, size_t, uint32_t, uint32_t,
- char *, uint8_t);
-struct jffs2_raw_dirent *resolvename(char *, size_t, uint32_t, char *, uint8_t);
-struct jffs2_raw_dirent *resolveinode(char *, size_t, uint32_t);
-
-struct jffs2_raw_dirent *resolvepath0(char *, size_t, uint32_t, const char *,
- uint32_t *, int);
-struct jffs2_raw_dirent *resolvepath(char *, size_t, uint32_t, const char *,
- uint32_t *);
-
-void lsdir(char *, size_t, const char *, int, int);
-void catfile(char *, size_t, char *, char *, size_t, size_t *);
-
-int main(int, char **);
-
-/* writes file node into buffer, to the proper position. */
-/* reading all valid nodes in version order reconstructs the file. */
-
-/*
- b - buffer
- bsize - buffer size
- rsize - result size
- n - node
- */
-
-void putblock(char *b, size_t bsize, size_t * rsize,
- struct jffs2_raw_inode *n)
-{
- uLongf dlen = je32_to_cpu(n->dsize);
-
- if (je32_to_cpu(n->isize) > bsize || (je32_to_cpu(n->offset) + dlen) > bsize)
- errmsg_die("File does not fit into buffer!");
-
- if (*rsize < je32_to_cpu(n->isize))
- bzero(b + *rsize, je32_to_cpu(n->isize) - *rsize);
-
- switch (n->compr) {
- case JFFS2_COMPR_ZLIB:
- uncompress((Bytef *) b + je32_to_cpu(n->offset), &dlen,
- (Bytef *) ((char *) n) + sizeof(struct jffs2_raw_inode),
- (uLongf) je32_to_cpu(n->csize));
- break;
-
- case JFFS2_COMPR_NONE:
- memcpy(b + je32_to_cpu(n->offset),
- ((char *) n) + sizeof(struct jffs2_raw_inode), dlen);
- break;
-
- case JFFS2_COMPR_ZERO:
- bzero(b + je32_to_cpu(n->offset), dlen);
- break;
-
- /* [DYN]RUBIN support required! */
-
- default:
- errmsg_die("Unsupported compression method!");
- }
-
- *rsize = je32_to_cpu(n->isize);
-}
-
-/* adds/removes directory node into dir struct. */
-/* reading all valid nodes in version order reconstructs the directory. */
-
-/*
- dd - directory struct being processed
- n - node
-
- return value: directory struct value replacing dd
- */
-
-struct dir *putdir(struct dir *dd, struct jffs2_raw_dirent *n)
-{
- struct dir *o, *d, *p;
-
- o = dd;
-
- if (je32_to_cpu(n->ino)) {
- if (dd == NULL) {
- d = xmalloc(sizeof(struct dir));
- d->type = n->type;
- memcpy(d->name, n->name, n->nsize);
- d->nsize = n->nsize;
- d->ino = je32_to_cpu(n->ino);
- d->next = NULL;
-
- return d;
- }
-
- while (1) {
- if (n->nsize == dd->nsize &&
- !memcmp(n->name, dd->name, n->nsize)) {
- dd->type = n->type;
- dd->ino = je32_to_cpu(n->ino);
-
- return o;
- }
-
- if (dd->next == NULL) {
- dd->next = xmalloc(sizeof(struct dir));
- dd->next->type = n->type;
- memcpy(dd->next->name, n->name, n->nsize);
- dd->next->nsize = n->nsize;
- dd->next->ino = je32_to_cpu(n->ino);
- dd->next->next = NULL;
-
- return o;
- }
-
- dd = dd->next;
- }
- } else {
- if (dd == NULL)
- return NULL;
-
- if (n->nsize == dd->nsize && !memcmp(n->name, dd->name, n->nsize)) {
- d = dd->next;
- free(dd);
- return d;
- }
-
- while (1) {
- p = dd;
- dd = dd->next;
-
- if (dd == NULL)
- return o;
-
- if (n->nsize == dd->nsize &&
- !memcmp(n->name, dd->name, n->nsize)) {
- p->next = dd->next;
- free(dd);
-
- return o;
- }
- }
- }
-}
-
-
-#define TYPEINDEX(mode) (((mode) >> 12) & 0x0f)
-#define TYPECHAR(mode) ("0pcCd?bB-?l?s???" [TYPEINDEX(mode)])
-
-/* The special bits. If set, display SMODE0/1 instead of MODE0/1 */
-static const mode_t SBIT[] = {
- 0, 0, S_ISUID,
- 0, 0, S_ISGID,
- 0, 0, S_ISVTX
-};
-
-/* The 9 mode bits to test */
-static const mode_t MBIT[] = {
- S_IRUSR, S_IWUSR, S_IXUSR,
- S_IRGRP, S_IWGRP, S_IXGRP,
- S_IROTH, S_IWOTH, S_IXOTH
-};
-
-static const char MODE1[] = "rwxrwxrwx";
-static const char MODE0[] = "---------";
-static const char SMODE1[] = "..s..s..t";
-static const char SMODE0[] = "..S..S..T";
-
-/*
- * Return the standard ls-like mode string from a file mode.
- * This is static and so is overwritten on each call.
- */
-const char *mode_string(int mode)
-{
- static char buf[12];
-
- int i;
-
- buf[0] = TYPECHAR(mode);
- for (i = 0; i < 9; i++) {
- if (mode & SBIT[i])
- buf[i + 1] = (mode & MBIT[i]) ? SMODE1[i] : SMODE0[i];
- else
- buf[i + 1] = (mode & MBIT[i]) ? MODE1[i] : MODE0[i];
- }
- return buf;
-}
-
-/* prints contents of directory structure */
-
-/*
- d - dir struct
- */
-
-void printdir(char *o, size_t size, struct dir *d, const char *path, int recurse,
- int want_ctime)
-{
- char m;
- char *filetime;
- time_t age;
- struct jffs2_raw_inode *ri;
- jint32_t mode;
-
- if (!path)
- return;
- if (strlen(path) == 1 && *path == '/')
- path++;
-
- while (d != NULL) {
- switch (d->type) {
- case DT_REG:
- m = ' ';
- break;
-
- case DT_FIFO:
- m = '|';
- break;
-
- case DT_CHR:
- m = ' ';
- break;
-
- case DT_BLK:
- m = ' ';
- break;
-
- case DT_DIR:
- m = '/';
- break;
-
- case DT_LNK:
- m = ' ';
- break;
-
- case DT_SOCK:
- m = '=';
- break;
-
- default:
- m = '?';
- }
- ri = find_raw_inode(o, size, d->ino);
- if (!ri) {
- warnmsg("bug: raw_inode missing!");
- d = d->next;
- continue;
- }
-
- filetime = ctime((const time_t *) &(ri->ctime));
- age = time(NULL) - je32_to_cpu(ri->ctime);
- mode.v32 = ri->mode.m;
- printf("%s %-4d %-8d %-8d ", mode_string(je32_to_cpu(mode)),
- 1, je16_to_cpu(ri->uid), je16_to_cpu(ri->gid));
- if ( d->type==DT_BLK || d->type==DT_CHR ) {
- dev_t rdev;
- size_t devsize;
- putblock((char*)&rdev, sizeof(rdev), &devsize, ri);
- printf("%4d, %3d ", major(rdev), minor(rdev));
- } else {
- printf("%9ld ", (long)je32_to_cpu(ri->dsize));
- }
- d->name[d->nsize]='\0';
- if (want_ctime) {
- if (age < 3600L * 24 * 365 / 2 && age > -15 * 60)
- /* hh:mm if less than 6 months old */
- printf("%6.6s %5.5s ", filetime + 4, filetime + 11);
- else
- printf("%6.6s %4.4s ", filetime + 4, filetime + 20);
- }
- printf("%s/%s%c", path, d->name, m);
- if (d->type == DT_LNK) {
- char symbuf[1024];
- size_t symsize;
- putblock(symbuf, sizeof(symbuf), &symsize, ri);
- symbuf[symsize] = 0;
- printf(" -> %s", symbuf);
- }
- printf("\n");
-
- if (d->type == DT_DIR && recurse) {
- char *tmp;
- tmp = xmalloc(BUFSIZ);
- sprintf(tmp, "%s/%s", path, d->name);
- lsdir(o, size, tmp, recurse, want_ctime); /* Go recursive */
- free(tmp);
- }
-
- d = d->next;
- }
-}
-
-/* frees memory used by directory structure */
-
-/*
- d - dir struct
- */
-
-void freedir(struct dir *d)
-{
- struct dir *t;
-
- while (d != NULL) {
- t = d->next;
- free(d);
- d = t;
- }
-}
-
-/* collects directory/file nodes in version order. */
-
-/*
- f - file flag.
- if zero, collect file, compare ino to inode
- otherwise, collect directory, compare ino to parent inode
- o - filesystem image pointer
- size - size of filesystem image
- ino - inode to compare against. see f.
-
- return value: a jffs2_raw_inode that corresponds the the specified
- inode, or NULL
- */
-
-struct jffs2_raw_inode *find_raw_inode(char *o, size_t size, uint32_t ino)
-{
- /* aligned! */
- union jffs2_node_union *n;
- union jffs2_node_union *e = (union jffs2_node_union *) (o + size);
- union jffs2_node_union *lr; /* last block position */
- union jffs2_node_union *mp = NULL; /* minimum position */
-
- uint32_t vmin, vmint, vmaxt, vmax, vcur, v;
-
- vmin = 0; /* next to read */
- vmax = ~((uint32_t) 0); /* last to read */
- vmint = ~((uint32_t) 0);
- vmaxt = 0; /* found maximum */
- vcur = 0; /* XXX what is smallest version number used? */
- /* too low version number can easily result excess log rereading */
-
- n = (union jffs2_node_union *) o;
- lr = n;
-
- do {
- while (n < e && je16_to_cpu(n->u.magic) != JFFS2_MAGIC_BITMASK)
- ADD_BYTES(n, 4);
-
- if (n < e && je16_to_cpu(n->u.magic) == JFFS2_MAGIC_BITMASK) {
- if (je16_to_cpu(n->u.nodetype) == JFFS2_NODETYPE_INODE &&
- je32_to_cpu(n->i.ino) == ino && (v = je32_to_cpu(n->i.version)) > vcur) {
- /* XXX crc check */
-
- if (vmaxt < v)
- vmaxt = v;
- if (vmint > v) {
- vmint = v;
- mp = n;
- }
-
- if (v == (vcur + 1))
- return (&(n->i));
- }
-
- ADD_BYTES(n, ((je32_to_cpu(n->u.totlen) + 3) & ~3));
- } else
- n = (union jffs2_node_union *) o; /* we're at the end, rewind to the beginning */
-
- if (lr == n) { /* whole loop since last read */
- vmax = vmaxt;
- vmin = vmint;
- vmint = ~((uint32_t) 0);
-
- if (vcur < vmax && vcur < vmin)
- return (&(mp->i));
- }
- } while (vcur < vmax);
-
- return NULL;
-}
-
-/* collects dir struct for selected inode */
-
-/*
- o - filesystem image pointer
- size - size of filesystem image
- pino - inode of the specified directory
- d - input directory structure
-
- return value: result directory structure, replaces d.
- */
-
-struct dir *collectdir(char *o, size_t size, uint32_t ino, struct dir *d)
-{
- /* aligned! */
- union jffs2_node_union *n;
- union jffs2_node_union *e = (union jffs2_node_union *) (o + size);
- union jffs2_node_union *lr; /* last block position */
- union jffs2_node_union *mp = NULL; /* minimum position */
-
- uint32_t vmin, vmint, vmaxt, vmax, vcur, v;
-
- vmin = 0; /* next to read */
- vmax = ~((uint32_t) 0); /* last to read */
- vmint = ~((uint32_t) 0);
- vmaxt = 0; /* found maximum */
- vcur = 0; /* XXX what is smallest version number used? */
- /* too low version number can easily result excess log rereading */
-
- n = (union jffs2_node_union *) o;
- lr = n;
-
- do {
- while (n < e && je16_to_cpu(n->u.magic) != JFFS2_MAGIC_BITMASK)
- ADD_BYTES(n, 4);
-
- if (n < e && je16_to_cpu(n->u.magic) == JFFS2_MAGIC_BITMASK) {
- if (je16_to_cpu(n->u.nodetype) == JFFS2_NODETYPE_DIRENT &&
- je32_to_cpu(n->d.pino) == ino && (v = je32_to_cpu(n->d.version)) > vcur) {
- /* XXX crc check */
-
- if (vmaxt < v)
- vmaxt = v;
- if (vmint > v) {
- vmint = v;
- mp = n;
- }
-
- if (v == (vcur + 1)) {
- d = putdir(d, &(n->d));
-
- lr = n;
- vcur++;
- vmint = ~((uint32_t) 0);
- }
- }
-
- ADD_BYTES(n, ((je32_to_cpu(n->u.totlen) + 3) & ~3));
- } else
- n = (union jffs2_node_union *) o; /* we're at the end, rewind to the beginning */
-
- if (lr == n) { /* whole loop since last read */
- vmax = vmaxt;
- vmin = vmint;
- vmint = ~((uint32_t) 0);
-
- if (vcur < vmax && vcur < vmin) {
- d = putdir(d, &(mp->d));
-
- lr = n =
- (union jffs2_node_union *) (((char *) mp) +
- ((je32_to_cpu(mp->u.totlen) + 3) & ~3));
-
- vcur = vmin;
- }
- }
- } while (vcur < vmax);
-
- return d;
-}
-
-
-
-/* resolve dirent based on criteria */
-
-/*
- o - filesystem image pointer
- size - size of filesystem image
- ino - if zero, ignore,
- otherwise compare against dirent inode
- pino - if zero, ingore,
- otherwise compare against parent inode
- and use name and nsize as extra criteria
- name - name of wanted dirent, used if pino!=0
- nsize - length of name of wanted dirent, used if pino!=0
-
- return value: pointer to relevant dirent structure in
- filesystem image or NULL
- */
-
-struct jffs2_raw_dirent *resolvedirent(char *o, size_t size,
- uint32_t ino, uint32_t pino,
- char *name, uint8_t nsize)
-{
- /* aligned! */
- union jffs2_node_union *n;
- union jffs2_node_union *e = (union jffs2_node_union *) (o + size);
-
- struct jffs2_raw_dirent *dd = NULL;
-
- uint32_t vmax, v;
-
- if (!pino && ino <= 1)
- return dd;
-
- vmax = 0;
-
- n = (union jffs2_node_union *) o;
-
- do {
- while (n < e && je16_to_cpu(n->u.magic) != JFFS2_MAGIC_BITMASK)
- ADD_BYTES(n, 4);
-
- if (n < e && je16_to_cpu(n->u.magic) == JFFS2_MAGIC_BITMASK) {
- if (je16_to_cpu(n->u.nodetype) == JFFS2_NODETYPE_DIRENT &&
- (!ino || je32_to_cpu(n->d.ino) == ino) &&
- (v = je32_to_cpu(n->d.version)) > vmax &&
- (!pino || (je32_to_cpu(n->d.pino) == pino &&
- nsize == n->d.nsize &&
- !memcmp(name, n->d.name, nsize)))) {
- /* XXX crc check */
-
- if (vmax < v) {
- vmax = v;
- dd = &(n->d);
- }
- }
-
- ADD_BYTES(n, ((je32_to_cpu(n->u.totlen) + 3) & ~3));
- } else
- return dd;
- } while (1);
-}
-
-/* resolve name under certain parent inode to dirent */
-
-/*
- o - filesystem image pointer
- size - size of filesystem image
- pino - requested parent inode
- name - name of wanted dirent
- nsize - length of name of wanted dirent
-
- return value: pointer to relevant dirent structure in
- filesystem image or NULL
- */
-
-struct jffs2_raw_dirent *resolvename(char *o, size_t size, uint32_t pino,
- char *name, uint8_t nsize)
-{
- return resolvedirent(o, size, 0, pino, name, nsize);
-}
-
-/* resolve inode to dirent */
-
-/*
- o - filesystem image pointer
- size - size of filesystem image
- ino - compare against dirent inode
-
- return value: pointer to relevant dirent structure in
- filesystem image or NULL
- */
-
-struct jffs2_raw_dirent *resolveinode(char *o, size_t size, uint32_t ino)
-{
- return resolvedirent(o, size, ino, 0, NULL, 0);
-}
-
-/* resolve slash-style path into dirent and inode.
- slash as first byte marks absolute path (root=inode 1).
- . and .. are resolved properly, and symlinks are followed.
- */
-
-/*
- o - filesystem image pointer
- size - size of filesystem image
- ino - root inode, used if path is relative
- p - path to be resolved
- inos - result inode, zero if failure
- recc - recursion count, to detect symlink loops
-
- return value: pointer to dirent struct in file system image.
- note that root directory doesn't have dirent struct
- (return value is NULL), but it has inode (*inos=1)
- */
-
-struct jffs2_raw_dirent *resolvepath0(char *o, size_t size, uint32_t ino,
- const char *p, uint32_t * inos, int recc)
-{
- struct jffs2_raw_dirent *dir = NULL;
-
- int d = 1;
- uint32_t tino;
-
- char *next;
-
- char *path, *pp;
-
- char symbuf[1024];
- size_t symsize;
-
- if (recc > 16) {
- /* probably symlink loop */
- *inos = 0;
- return NULL;
- }
-
- pp = path = xstrdup(p);
-
- if (*path == '/') {
- path++;
- ino = 1;
- }
-
- if (ino > 1) {
- dir = resolveinode(o, size, ino);
-
- ino = DIRENT_INO(dir);
- }
-
- next = path - 1;
-
- while (ino && next != NULL && next[1] != 0 && d) {
- path = next + 1;
- next = strchr(path, '/');
-
- if (next != NULL)
- *next = 0;
-
- if (*path == '.' && path[1] == 0)
- continue;
- if (*path == '.' && path[1] == '.' && path[2] == 0) {
- if (DIRENT_PINO(dir) == 1) {
- ino = 1;
- dir = NULL;
- } else {
- dir = resolveinode(o, size, DIRENT_PINO(dir));
- ino = DIRENT_INO(dir);
- }
-
- continue;
- }
-
- dir = resolvename(o, size, ino, path, (uint8_t) strlen(path));
-
- if (DIRENT_INO(dir) == 0 ||
- (next != NULL &&
- !(dir->type == DT_DIR || dir->type == DT_LNK))) {
- free(pp);
-
- *inos = 0;
-
- return NULL;
- }
-
- if (dir->type == DT_LNK) {
- struct jffs2_raw_inode *ri;
- ri = find_raw_inode(o, size, DIRENT_INO(dir));
- putblock(symbuf, sizeof(symbuf), &symsize, ri);
- symbuf[symsize] = 0;
-
- tino = ino;
- ino = 0;
-
- dir = resolvepath0(o, size, tino, symbuf, &ino, ++recc);
-
- if (dir != NULL && next != NULL &&
- !(dir->type == DT_DIR || dir->type == DT_LNK)) {
- free(pp);
-
- *inos = 0;
- return NULL;
- }
- }
- if (dir != NULL)
- ino = DIRENT_INO(dir);
- }
-
- free(pp);
-
- *inos = ino;
-
- return dir;
-}
-
-/* resolve slash-style path into dirent and inode.
- slash as first byte marks absolute path (root=inode 1).
- . and .. are resolved properly, and symlinks are followed.
- */
-
-/*
- o - filesystem image pointer
- size - size of filesystem image
- ino - root inode, used if path is relative
- p - path to be resolved
- inos - result inode, zero if failure
-
- return value: pointer to dirent struct in file system image.
- note that root directory doesn't have dirent struct
- (return value is NULL), but it has inode (*inos=1)
- */
-
-struct jffs2_raw_dirent *resolvepath(char *o, size_t size, uint32_t ino,
- const char *p, uint32_t * inos)
-{
- return resolvepath0(o, size, ino, p, inos, 0);
-}
-
-/* lists files on directory specified by path */
-
-/*
- o - filesystem image pointer
- size - size of filesystem image
- p - path to be resolved
- */
-
-void lsdir(char *o, size_t size, const char *path, int recurse, int want_ctime)
-{
- struct jffs2_raw_dirent *dd;
- struct dir *d = NULL;
-
- uint32_t ino;
-
- dd = resolvepath(o, size, 1, path, &ino);
-
- if (ino == 0 ||
- (dd == NULL && ino == 0) || (dd != NULL && dd->type != DT_DIR))
- errmsg_die("%s: No such file or directory", path);
-
- d = collectdir(o, size, ino, d);
- printdir(o, size, d, path, recurse, want_ctime);
- freedir(d);
-}
-
-/* writes file specified by path to the buffer */
-
-/*
- o - filesystem image pointer
- size - size of filesystem image
- p - path to be resolved
- b - file buffer
- bsize - file buffer size
- rsize - file result size
- */
-
-void catfile(char *o, size_t size, char *path, char *b, size_t bsize,
- size_t * rsize)
-{
- struct jffs2_raw_dirent *dd;
- struct jffs2_raw_inode *ri;
- uint32_t ino;
-
- dd = resolvepath(o, size, 1, path, &ino);
-
- if (ino == 0)
- errmsg_die("%s: No such file or directory", path);
-
- if (dd == NULL || dd->type != DT_REG)
- errmsg_die("%s: Not a regular file", path);
-
- ri = find_raw_inode(o, size, ino);
- putblock(b, bsize, rsize, ri);
-
- write(1, b, *rsize);
-}
-
-/* usage example */
-
-int main(int argc, char **argv)
-{
- int fd, opt, recurse = 0, want_ctime = 0;
- struct stat st;
-
- char *scratch, *dir = NULL, *file = NULL;
- size_t ssize = 0;
-
- char *buf;
-
- while ((opt = getopt(argc, argv, "rd:f:t")) > 0) {
- switch (opt) {
- case 'd':
- dir = optarg;
- break;
- case 'f':
- file = optarg;
- break;
- case 'r':
- recurse++;
- break;
- case 't':
- want_ctime++;
- break;
- default:
- fprintf(stderr,
- "Usage: %s <image> [-d|-f] < path >\n",
- PROGRAM_NAME);
- exit(EXIT_FAILURE);
- }
- }
-
- fd = open(argv[optind], O_RDONLY);
- if (fd == -1)
- sys_errmsg_die("%s", argv[optind]);
-
- if (fstat(fd, &st))
- sys_errmsg_die("%s", argv[optind]);
-
- buf = xmalloc((size_t) st.st_size);
-
- if (read(fd, buf, st.st_size) != (ssize_t) st.st_size)
- sys_errmsg_die("%s", argv[optind]);
-
- if (dir)
- lsdir(buf, st.st_size, dir, recurse, want_ctime);
-
- if (file) {
- scratch = xmalloc(SCRATCH_SIZE);
-
- catfile(buf, st.st_size, file, scratch, SCRATCH_SIZE, &ssize);
- free(scratch);
- }
-
- if (!dir && !file)
- lsdir(buf, st.st_size, "/", 1, want_ctime);
-
-
- free(buf);
- exit(EXIT_SUCCESS);
-}