?? cramfs_cb.c
字號(hào):
#ifndef CRAMFS_CB_C
#define CRAMFS_CB_C
//---------------------------------------------------------
/* Exit codes used by mkfs-type programs */
#define MKFS_OK 0 /* No errors */
#define MKFS_ERROR 8 /* Operational error */
#define MKFS_USAGE 16 /* Usage or syntax error */
/* The kernel only supports PAD_SIZE of 0 and 512. */
#define PAD_SIZE 512
/* The kernel assumes PAGE_CACHE_SIZE as block size. */
#define PAGE_CACHE_SIZE (4096)
/*
* The longest filename component to allow for in the input directory tree.
* ext2fs (and many others) allow up to 255 bytes. A couple of filesystems
* allow longer (e.g. smbfs 1024), but there isn't much use in supporting
* >255-byte names in the input directory tree given that such names get
* truncated to CRAMFS_MAXPATHLEN (252 bytes) when written to cramfs.
*
* Old versions of mkcramfs generated corrupted filesystems if any input
* filenames exceeded CRAMFS_MAXPATHLEN (252 bytes), however old
* versions of cramfsck seem to have been able to detect the corruption.
*/
#define MAX_INPUT_NAMELEN 255
/*
* Maximum size fs you can create is roughly 256MB. (The last file's
* data must begin within 256MB boundary but can extend beyond that.)
*
* Note that if you want it to fit in a ROM then you're limited to what the
* hardware and kernel can support.
*/
#define MAXFSLEN ((((1 << CRAMFS_OFFSET_WIDTH) - 1) << 2) /* offset */ \
+ (1 << CRAMFS_SIZE_WIDTH) - 1 /* filesize */ \
+ (1 << CRAMFS_SIZE_WIDTH) * 4 / PAGE_CACHE_SIZE /* block pointers */ )
static const char *progname = "mkcramfs";
static unsigned int blksize = PAGE_CACHE_SIZE;
static long total_blocks = 0, total_nodes = 1; /* pre-count the root node */
static int image_length = 0;
/*
* If opt_holes is set, then mkcramfs can create explicit holes in the
* data, which saves 26 bytes per hole (which is a lot smaller a
* saving than most most filesystems).
*
* Note that kernels up to at least 2.3.39 don't support cramfs holes,
* which is why this is turned off by default.
*
* If opt_verbose is 1, be verbose. If it is higher, be even more verbose.
*/
static u32 opt_edition = 0;
static int opt_errors = 0;
static int opt_holes = 0;
static int opt_pad = 0;
static int opt_verbose = 0;
static char *opt_image = NULL;
static char *opt_name = NULL;
static int warn_dev, warn_gid, warn_namelen, warn_skip, warn_size, warn_uid;
//---------------------------------------------------------
/* In-core version of inode / directory entry. */
struct entry {
/* stats */
unsigned char *name;
unsigned int mode, size, uid, gid;
/* these are only used for non-empty files */
char *path; /* always null except non-empty files */
int fd; /* temporarily open files while mmapped */
HANDLE fh; /*append by mordecay, for file mmap in winNT*/
HANDLE fm; /*append by mordecay, for file mmap in winNT*/
/* FS data */
void *uncompressed;
/* points to other identical file */
struct entry *same;
unsigned int offset; /* pointer to compressed data in archive */
unsigned int dir_offset; /* Where in the archive is the directory entry? */
/* organization */
struct entry *child; /* null for non-directories and empty directories */
struct entry *next;
};
//---------------------------------------------------------
/* Input status of 0 to print help and exit without an error. */
static void usage(int status)
{
/*
FILE *stream = status ? stderr : stdout;
fprintf(stream, "usage: %s [-h] [-e edition] [-i file] [-n name] dirname outfile\n"
" -h print this help\n"
" -E make all warnings errors (non-zero exit status)\n"
" -e edition set edition number (part of fsid)\n"
" -i file insert a file image into the filesystem (requires >= 2.4.0)\n"
" -n name set name of cramfs filesystem\n"
" -p pad by %d bytes for boot code\n"
" -s sort directory entries (old option, ignored)\n"
" -v be more verbose\n"
" -z make explicit holes (requires >= 2.3.39)\n"
" dirname root of the directory tree to be compressed\n"
" outfile output file\n", progname, PAD_SIZE);
*/
exit(status);
}
//---------------------------------------------------------
static void die(int status, int syserr, const char *fmt, ...)
{
va_list arg_ptr;
char stext[512];
va_start(arg_ptr, fmt);
vsprintf(stext, fmt, arg_ptr);
va_end(arg_ptr);
ShowMessage(stext);
exit(status);
}
//---------------------------------------------------------
static void map_entry(struct entry *entry)
{
/*
if (entry->path) {
entry->fd = open(entry->path, O_RDONLY);
if (entry->fd < 0) {
die(MKFS_ERROR, 1, "open failed: %s", entry->path);
}
entry->uncompressed = mmap(NULL, entry->size, PROT_READ, MAP_PRIVATE, entry->fd, 0);
if (entry->uncompressed == MAP_FAILED) {
die(MKFS_ERROR, 1, "mmap failed: %s", entry->path);
}
}
*/
if(entry->path)
{
DWORD f_size;
DWORD Access = GENERIC_READ;
DWORD AShare = FILE_SHARE_READ;
DWORD Create = OPEN_EXISTING;
DWORD Attrib = FILE_FLAG_SEQUENTIAL_SCAN;
entry->fh = CreateFile(
entry->path, Access, AShare, 0, Create, Attrib, 0);
if(entry->fh == INVALID_HANDLE_VALUE)
{
die(MKFS_ERROR, 1, "open failed: %s", entry->path);
}
f_size = SetFilePointer(entry->fh, 0, 0, FILE_END);
SetFilePointer(entry->fh, 0, 0, FILE_BEGIN);
entry->fd = (int)entry->fh;
entry->fm = CreateFileMapping(
entry->fh, NULL, PAGE_READONLY, 0, f_size, NULL);
if(entry->fm == INVALID_HANDLE_VALUE)
{
die(MKFS_ERROR, 1, "fmap failed: %s", entry->path);
}
entry->uncompressed = MapViewOfFile(
entry->fm, FILE_MAP_READ, 0, 0, f_size);
if(entry->uncompressed == NULL)
{
die(MKFS_ERROR, 1, "mapv failed: %s", entry->path);
}
}
}
//---------------------------------------------------------
static void unmap_entry(struct entry *entry)
{
/*
if (entry->path) {
if (munmap(entry->uncompressed, entry->size) < 0) {
die(MKFS_ERROR, 1, "munmap failed: %s", entry->path);
}
close(entry->fd);
}
*/
if(entry->path)
{
UnmapViewOfFile(entry->uncompressed);
CloseHandle(entry->fm);
CloseHandle(entry->fh);
entry->fm = INVALID_HANDLE_VALUE;
entry->fh = INVALID_HANDLE_VALUE;
}
}
//---------------------------------------------------------
static int find_identical_file(struct entry *orig, struct entry *newfile)
{
if (orig == newfile)
return 1;
if (!orig)
return 0;
if (orig->size == newfile->size && (orig->path || orig->uncompressed))
{
map_entry(orig);
map_entry(newfile);
if (!memcmp(orig->uncompressed, newfile->uncompressed, orig->size))
{
newfile->same = orig;
unmap_entry(newfile);
unmap_entry(orig);
return 1;
}
unmap_entry(newfile);
unmap_entry(orig);
}
return (find_identical_file(orig->child, newfile) ||
find_identical_file(orig->next, newfile));
}
//---------------------------------------------------------
static void eliminate_doubles(struct entry *root, struct entry *orig) {
if (orig) {
if (orig->size && (orig->path || orig->uncompressed))
find_identical_file(root, orig);
eliminate_doubles(root, orig->child);
eliminate_doubles(root, orig->next);
}
}
//---------------------------------------------------------
/*
* We define our own sorting function instead of using alphasort which
* uses strcoll and changes ordering based on locale information.
*/
struct dirent
{
int d_ino;
int d_off;
short d_reclen;
unsigned char d_type;
char d_name[256];
} g_dirent_array[65536];
static int cramsort(const void *a, const void *b)
{
return strcmp ((*(const struct dirent **) a)->d_name,
(*(const struct dirent **) b)->d_name);
}
static int scandir(const char *path,
struct dirent ***name_list,
int (*select)(const void *),
int (*compar)(const void *, const void *))
{
int i = 1;
TSearchRec search_rec;
AnsiString search_str;
search_str.sprintf("%s\\*.*",path);
if(FindFirst(search_str, faAnyFile, search_rec) == 0)
{
(*name_list) = (struct dirent **)
malloc(sizeof(long[65536]));
(*name_list)[0] = g_dirent_array;
StrPLCopy(g_dirent_array->d_name,
search_rec.Name, 255);
while(0 == FindNext(search_rec))
{
(*name_list)[i] = g_dirent_array + i;
StrPLCopy(g_dirent_array[i].d_name,
search_rec.Name, 255);
if((i ++) >= 65535)
break;
};
FindClose(search_rec);
qsort((*name_list), i, sizeof(long), compar);
return(i);
}
return(-1);
}
//---------------------------------------------------------
struct stat
{
DWORD st_dev;
DWORD st_ino;
DWORD st_mode;
DWORD st_nlink;
DWORD st_uid;
DWORD st_gid;
DWORD st_rdev;
DWORD st_size;
DWORD st_blksize;
DWORD st_blocks;
DWORD st_atime;
DWORD st_mtime;
DWORD st_ctime;
};
//---------------------------------------------------------
#define S_IFMT 0170000
#define S_IFDIR 0040000
#define S_IFREG 0100000
#define S_ISDIR(x) (((x) & S_IFDIR) == S_IFDIR)
#define S_ISREG(x) (((x) & S_IFREG) == S_IFREG)
//---------------------------------------------------------
static int lstat(const char *file_name, struct stat *buf)
{
memset(buf, 0, sizeof(stat));
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -