📄 genromfs.c
字号:
}/* Node manipulating functions */void freenode(struct filenode *n){ /* Rare, not yet */}void setnode(struct filenode *n, dev_t dev, ino_t ino, mode_t um){ n->ondev = dev; n->onino = ino; n->modes = um;}struct filenode *newnode(const char *base, const char *name, int curroffset){ struct filenode *node; int len; char *str; node = malloc(sizeof (*node)); if (!node) { fprintf(stderr,"out of memory\n"); exit(1); } len = strlen(name); str = malloc(len+1); if (!str) { fprintf(stderr,"out of memory\n"); exit(1); } strcpy(str, name); node->name = str; if (!curroffset) { len = 1; name = "."; } if (strlen(base)) len++; str = malloc(strlen(base)+len+1); if (!str) { fprintf(stderr,"out of memory\n"); exit(1); } if (strlen(base)) { sprintf(str, "%s/%s", base, name); } else { strcpy(str, name); } node->realname = str; node->next = node->prev = NULL; node->parent = NULL; initlist(&node->dirlist, node); node->ondev = -1; node->onino = -1; node->modes = -1; node->size = 0; node->devnode = 0; node->orig_link = NULL; node->offset = curroffset; node->pad = 0; return node;}struct filenode *findnode(struct filenode *node, dev_t dev, ino_t ino){ struct filenode *found, *p; /* scan the whole tree */ if (node->ondev == dev && node->onino == ino) return node; p = node->dirlist.head; while (p->next) { found = findnode(p, dev, ino); if (found) return found; p = p->next; } return NULL;}#define ALIGNUP16(x) (((x)+15)&~15)int spaceneeded(struct filenode *node){ return 16 + ALIGNUP16(strlen(node->name)+1) + ALIGNUP16(node->size);}int alignnode(struct filenode *node, int curroffset, int extraspace){ int align = findalign(node), d; d = ((curroffset + extraspace) & (align - 1)); if (d) { align -= d; curroffset += align; node->offset += align; node->pad = align; } return curroffset;}int processdir(int level, const char *base, const char *dirname, struct stat *sb, struct filenode *dir, struct filenode *root, int curroffset){ DIR *dirfd; struct dirent *dp; struct filenode *n, *link; struct excludes *pe; if (level <= 1) { /* Ok, to make sure . and .. are handled correctly * we add them first. Note also that we alloc them * first to get to know the real name */ link = newnode(base, ".", curroffset); if (!lstat(link->realname, sb)) { setnode(link, sb->st_dev, sb->st_ino, sb->st_mode); append(&dir->dirlist, link); /* special case for root node - '..'s in subdirs should link to * '.' of root node, not root node itself. */ dir->dirlist.owner = link; curroffset = alignnode(link, curroffset, 0) + spaceneeded(link); n = newnode(base, "..", curroffset); if (!lstat(n->realname, sb)) { setnode(n, sb->st_dev, sb->st_ino, sb->st_mode); append(&dir->dirlist, n); n->orig_link = link; curroffset = alignnode(n, curroffset, 0) + spaceneeded(n); } } } dirfd = opendir(dir->realname); if (dirfd == NULL) { perror(dir->realname); exit(1); } while(dirfd && (dp = readdir(dirfd))) { /* don't process main . and .. twice */ if (level <= 1 && (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)) continue; n = newnode(base, dp->d_name, curroffset); /* Process exclude list. */ for (pe = excludelist; pe; pe = pe->next) { if (!nodematch(pe->pattern, n)) { freenode(n); break; } } if (pe) continue; if (lstat(n->realname, sb)) { fprintf(stderr, "ignoring '%s' (lstat failed)\n", n->realname); freenode(n); continue; } /* strip 000_ from files/directories except '.' and '..' */ if (case_insensitive_mode && (strcmp(dp->d_name, ".") != 0 && strcmp(dp->d_name, "..") != 0)) { if(n->name[3] == 'x') // "001x_filename" If marked as executable then force exe permission. sb->st_mode |= S_IXUSR; n->name += 5; } /* Handle special names */ if ( n->name[0] == '@' ) { if (S_ISLNK(sb->st_mode)) { /* this is a link to follow at build time */ n->name = n->name + 1; /* strip off the leading @ */ memset(bigbuf, 0, sizeof(bigbuf)); readlink(n->realname, bigbuf, sizeof(bigbuf)); n->realname = strdup(bigbuf); if (lstat(n->realname, sb)) { fprintf(stderr, "ignoring '%s' (lstat failed)\n", n->realname); freenode(n); continue; } } else if (S_ISREG(sb->st_mode) && sb->st_size == 0) { /* * special file @name,[bcp..],major,minor */ char devname[32]; char type; int major; int minor; if (sscanf(n->name, "@%[a-zA-Z0-9_+-],%c,%d,%d", devname, &type, &major, &minor) == 4 ) { strcpy(n->name, devname); sb->st_rdev = makedev(major, minor); sb->st_mode &= ~S_IFMT; switch (type) { case 'c': case 'u': sb->st_mode |= S_IFCHR; break; case 'b': sb->st_mode |= S_IFBLK; break; case 'p': sb->st_mode |= S_IFIFO; break; default: fprintf(stderr, "Invalid special device type '%c' " "for file %s\n", type, n->realname); freenode(n); continue; } } } } setnode(n, sb->st_dev, sb->st_ino, sb->st_mode); /* Skip unreadable files/dirs */ if (!S_ISLNK(n->modes) && access(n->realname, R_OK)) { fprintf(stderr, "ignoring '%s' (access failed)\n", n->realname); freenode(n); continue; } /* Look up old links */ if ( strcmp(n->name, ".") == 0 ) { append(&dir->dirlist, n); link = n->parent; } else if (strcmp(n->name, "..") == 0) { append(&dir->dirlist, n); link = n->parent->parent; } else { link = findnode(root, n->ondev, n->onino); append(&dir->dirlist, n); } if (link) { n->orig_link = link; curroffset = alignnode(n, curroffset, 0) + spaceneeded(n); continue; } if (S_ISREG(sb->st_mode)) { curroffset = alignnode(n, curroffset, spaceneeded(n)); n->size = sb->st_size; } else curroffset = alignnode(n, curroffset, 0); if (S_ISLNK(sb->st_mode)) { n->size = sb->st_size; } curroffset += spaceneeded(n); if (S_ISCHR(sb->st_mode) || S_ISBLK(sb->st_mode)) { n->devnode = sb->st_rdev; } if (S_ISDIR(sb->st_mode)) { if (!strcmp(n->name, "..")) { curroffset = processdir(level+1, dir->realname, dp->d_name, sb, dir, root, curroffset); } else { curroffset = processdir(level+1, n->realname, dp->d_name, sb, n, root, curroffset); } } } if (dirfd) closedir(dirfd); return curroffset;}void showhelp(const char *argv0){ printf("genromfs \n"); printf("Usage: %s [OPTIONS] -f IMAGE\n",argv0); printf("Create a romfs filesystem image from a directory\n"); printf("\n"); printf(" -f IMAGE Output the image into this file\n"); printf(" -d DIRECTORY Use this directory as source\n"); printf(" -v (Too) verbose operation\n"); printf(" -V VOLUME Use the specified volume name\n"); printf(" -a ALIGN Align regular file data to ALIGN bytes\n"); printf(" -A ALIGN,PATTERN Align all objects matching pattern to at least ALIGN bytes\n"); printf(" -x PATTERN Exclude all objects matching pattern\n"); printf(" -i Case insensitive mode. Strip nnn_ from filenames in the image\n"); printf(" -h Show this help\n"); printf("\n"); printf("Report bugs to chexum@shadow.banki.hu\n");}int main(int argc, char *argv[]){ int c; char *dir = "."; char *outf = NULL; char *volname = NULL; int verbose=0; char buf[256]; struct filenode *root; struct stat sb; int lastoff; int i; char *p; struct aligns *pa, *pa2; struct excludes *pe, *pe2; FILE *f;#ifdef WIN32 case_insensitive_mode = 1; // We hardcode this for the Windows platform.#endif while ((c = getopt(argc, argv, "V:vd:f:ha:A:x:i")) != EOF) { switch(c) { case 'i': case_insensitive_mode = 1; break; case 'd': dir = optarg; break; case 'f': outf = optarg; break; case 'V': volname = optarg; break; case 'v': verbose = 1; break; case 'h': showhelp(argv[0]); exit(0); case 'a': align = strtoul(optarg, NULL, 0); if (align < 16 || (align & (align - 1))) { fprintf(stderr, "Align has to be at least 16 bytes and a power of two\n"); exit(1); } break; case 'A': i = strtoul(optarg, &p, 0); if (i < 16 || (i & (i - 1))) { fprintf(stderr, "Align has to be at least 16 bytes and a power of two\n"); exit(1); } if (*p != ',' || !p[1]) { fprintf(stderr, "-A takes N,PATTERN format of argument, where N is a number\n"); exit(1); } /* strlen(p+1) + 1 eq strlen(p) */ pa = (struct aligns *)malloc(sizeof(*pa) + strlen(p)); pa->align = i; pa->next = NULL; strcpy(pa->pattern, p + 1); if (!alignlist) alignlist = pa; else { for (pa2 = alignlist; pa2->next; pa2 = pa2->next) ; pa2->next = pa; } break; case 'x': pe = (struct excludes *)malloc(sizeof(*pe) + strlen(optarg) + 1); pe->next = NULL; strcpy(pe->pattern, optarg); if (!excludelist) excludelist = pe; else { for (pe2 = excludelist; pe2->next; pe2 = pe2->next) ; pe2->next = pe; } break; default: exit(1); } } if (!volname) { sprintf(buf, "rom %08lx", time(NULL)); volname = buf; } if (!outf) { fprintf(stderr, "%s: you must specify the destination file\n", argv[0]); fprintf(stderr, "Try `%s -h' for more information\n",argv[0]); exit(1); } if (strcmp(outf, "-") == 0) { f = fdopen(1,"wb"); } else f = fopen(outf, "wb"); if (!f) { perror(outf); exit(1); } realbase = strlen(dir); root = newnode(dir, volname, 0); root->parent = root; lastoff = processdir (1, dir, dir, &sb, root, root, spaceneeded(root)); if (verbose) shownode(0, root, stderr); dumpall(root, lastoff, f); exit(0);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -