void dumpall(struct filenode *node, int lastoff, FILE *f) { struct romfh ri; struct filenode *p; ri.nextfh = htonl(0x2d726f6d); ri.spec = htonl(0x3166732d); ri.size = htonl(lastoff); ri.checksum = htonl(0x55555555); dumpri(&ri, node, f); p = node->dirlist.head; while (p->next) { dumpnode(p, f); p = p->next; } /* Align the whole bunch to ROMBSIZE boundary */ if (lastoff&1023) dumpzero(1024-(lastoff&1023), f); }
int dumpnode(struct filenode *node, FILE *f) { struct romfh ri; struct filenode *p; ri.nextfh = 0; ri.spec = 0; ri.size = htonl(node->size); ri.checksum = htonl(0x55555555); if(node->pad) dumpzero(node->pad, f); if(node->next && node->next->next) ri.nextfh = htonl(node->next->offset); if((node->modes & 0111) && (S_ISDIR(node->modes) || S_ISREG(node->modes))) ri.nextfh |= htonl(ROMFH_EXEC); if(node->orig_link) { ri.nextfh |= htonl(ROMFH_HRD); /* Don't allow hardlinks to convey attributes */ ri.nextfh &= ~htonl(ROMFH_EXEC); ri.spec = htonl(node->orig_link->offset); dumpri(&ri, node, f); } else if(S_ISDIR(node->modes)) { ri.nextfh |= htonl(ROMFH_DIR); if(listisempty(&node->dirlist)) { ri.spec = htonl(node->offset); } else { ri.spec = htonl(node->dirlist.head->offset); } dumpri(&ri, node, f); } else if(S_ISLNK(node->modes)) { ri.nextfh |= htonl(ROMFH_LNK); dumpri(&ri, node, f); memset(bigbuf, 0, sizeof(bigbuf)); if(readlink(node->realname, bigbuf, node->size) < 0) { return 1; } dumpdataa(bigbuf, node->size, f); } else if(S_ISREG(node->modes)) { int offset, len, fd, max, avail; ri.nextfh |= htonl(ROMFH_REG); dumpri(&ri, node, f); offset = 0; max = node->size; /* XXX warn about size mismatch */ fd = open(node->realname, O_RDONLY #ifdef O_BINARY | O_BINARY #endif ); if(fd) { while(offset < max) { avail = max - offset < sizeof(bigbuf) ? max - offset : sizeof(bigbuf); len = read(fd, bigbuf, avail); if(len <= 0) break; dumpdata(bigbuf, len, f); offset += len; } close(fd); } max = (max + 15)&~15; while(offset < max) { avail = max - offset < sizeof(bigbuf) ? max - offset : sizeof(bigbuf); memset(bigbuf, 0, avail); dumpdata(bigbuf, avail, f); offset += avail; } } else if(S_ISCHR(node->modes)) { ri.nextfh |= htonl(ROMFH_CHR); ri.spec = htonl(major(node->devnode) << 16 | minor(node->devnode)); dumpri(&ri, node, f); } else if(S_ISBLK(node->modes)) { ri.nextfh |= htonl(ROMFH_BLK); ri.spec = htonl(major(node->devnode) << 16 | minor(node->devnode)); dumpri(&ri, node, f); } else if(S_ISFIFO(node->modes)) { ri.nextfh |= htonl(ROMFH_FIF); dumpri(&ri, node, f); } else if(S_ISSOCK(node->modes)) { ri.nextfh |= htonl(ROMFH_SCK); dumpri(&ri, node, f); } p = node->dirlist.head; while(p->next) { if(dumpnode(p, f)) { return 1; } p = p->next; } return 0; }