static int unixfs_internal_readlink(ino_t ino, char path[UNIXFS_MAXPATHLEN]) { struct inode* ip = unixfs_internal_iget(ino); if (!ip) return ENOENT; int error; struct cpio_newc_node_info* ci = (struct cpio_newc_node_info*)ip->I_private; if (!ci->ci_linktargetname) { error = ENOENT; goto out; } size_t linklen = min(ip->I_size, CPIO_NEWC_BLOCK); memcpy(path, ci->ci_linktargetname, linklen); path[linklen] = '\0'; error = 0; out: unixfs_internal_iput(ip); return error; }
static void unixfs_internal_fini(void* filsys) { struct super_block* sb = (struct super_block*)filsys; struct filsys* fs = (struct filsys*)sb->s_fs_info; ino_t i = fs->s_lastino; for (; i >= ROOTINO; i--) { struct inode* tmp = unixfs_internal_iget(i); if (tmp) { struct cpio_newc_node_info* ci = (struct cpio_newc_node_info*)tmp->I_private; if (ci) { free(ci->ci_name); if (ci->ci_linktargetname) free(ci->ci_linktargetname); } unixfs_internal_iput(tmp); unixfs_internal_iput(tmp); } } unixfs_inodelayer_fini(); if (sb) { if (sb->s_bdev >= 0) close(sb->s_bdev); sb->s_bdev = -1; if (sb->s_fs_info) free(sb->s_fs_info); } }
static int unixfs_internal_readlink(ino_t ino, char path[UNIXFS_MAXPATHLEN]) { struct inode* ip = unixfs_internal_iget(ino); if (!ip) return ENOENT; int error = 0; size_t linklen = (ip->I_size > UNIXFS_MAXPATHLEN - 1) ? UNIXFS_MAXPATHLEN - 1: ip->I_size; char page[PAGE_SIZE]; error = minixfs_get_page(ip, (off_t)0, page); if (error) goto out; memcpy(path, page, linklen); path[linklen] = '\0'; out: unixfs_internal_iput(ip); return error; }
static int unixfs_internal_igetattr(ino_t ino, struct stat* stbuf) { struct inode* ip = unixfs_internal_iget(ino); if (!ip) return ENOENT; unixfs_internal_istat(ip, stbuf); unixfs_internal_iput(ip); return 0; }
static int unixfs_internal_igetattr(ino_t ino, struct stat* stbuf) { if (ino == OSXFUSE_ROOTINO) ino = MINIX_ROOT_INO; struct inode* ip = unixfs_internal_iget(ino); if (!ip) return ENOENT; unixfs_internal_istat(ip, stbuf); unixfs_internal_iput(ip); return 0; }
static int unixfs_internal_namei(ino_t parentino, const char* name, struct stat* stbuf) { int ret = ENOENT; stbuf->st_ino = 0; size_t namelen = strlen(name); if (namelen > DIRSIZ) return ENAMETOOLONG; struct inode* dp = unixfs_internal_iget(parentino); if (!dp) return ENOENT; if (!S_ISDIR(dp->I_mode)) { ret = ENOTDIR; goto out; } struct ar_node_info* child = ((struct ar_node_info*)dp->I_private)->ar_children;; if (!child) { ret = ENOENT; goto out; } int found = 0; do { size_t target_namelen = strlen((const char*)child->ar_name); if ((namelen == target_namelen) && (memcmp(name, child->ar_name, target_namelen) == 0)) { found = 1; break; } child = child->ar_next_sibling; } while (child); if (found) ret = unixfs_internal_igetattr((ino_t)child->ar_self->I_ino, stbuf); out: unixfs_internal_iput(dp); return ret; }
static int unixfs_internal_nextdirentry(struct inode* dp, struct unixfs_dirbuf* dirbuf, off_t* offset, struct unixfs_direntry* dent) { if (*offset >= dp->I_size) return -1; if (*offset < 2) { int idx = 0; dent->name[idx++] = '.'; dent->ino = ROOTINO; if (*offset == 1) { if (dp->I_ino != ROOTINO) { struct inode* pdp = unixfs_internal_iget(dp->I_ino); if (pdp) { dent->ino = pdp->I_ino; unixfs_internal_iput(pdp); } } dent->name[idx++] = '.'; } dent->name[idx++] = '\0'; goto out; } struct cpio_newc_node_info* child = ((struct cpio_newc_node_info*)dp->I_private)->ci_children;; off_t i; for (i = 0; i < (*offset - 2); i++) child = child->ci_next_sibling; dent->ino = (ino_t)child->ci_self->I_ino; size_t dirnamelen = strlen(child->ci_name); dirnamelen = min(dirnamelen, UNIXFS_MAXNAMLEN); memcpy(dent->name, child->ci_name, dirnamelen); dent->name[dirnamelen] = '\0'; out: *offset += 1; return 0; }
static void unixfs_internal_fini(void* filsys) { struct super_block* sb = (struct super_block*)filsys; struct filsys* fs = (struct filsys*)sb->s_fs_info; ino_t i = fs->s_lastino; for (; i >= ROOTINO; i--) { struct inode* tmp = unixfs_internal_iget(i); if (tmp) { unixfs_internal_iput(tmp); unixfs_internal_iput(tmp); } } unixfs_inodelayer_fini(); if (sb) { if (sb->s_bdev >= 0) close(sb->s_bdev); sb->s_bdev = -1; if (sb->s_fs_info) free(sb->s_fs_info); } }
static void* unixfs_internal_init(const char* dmg, uint32_t flags, fs_endian_t fse, char** fsname, char** volname) { int fd = -1; if ((fd = open(dmg, O_RDONLY)) < 0) { perror("open"); return NULL; } int err; struct stat stbuf; struct super_block* sb = (struct super_block*)0; struct filsys* fs = (struct filsys*)0; if ((err = fstat(fd, &stbuf)) != 0) { perror("fstat"); goto out; } if (!S_ISREG(stbuf.st_mode) && !(flags & UNIXFS_FORCE)) { err = EINVAL; fprintf(stderr, "%s is not an ar image file\n", dmg); goto out; } uint16_t magic; if (read(fd, &magic, sizeof(uint16_t)) != sizeof(uint16_t)) { err = EIO; fprintf(stderr, "failed to read magic from file\n"); goto out; } uint16_t armagic = fs16_to_host(UNIXFS_FS_PDP, magic); fs_endian_t e = UNIXFS_FS_PDP; if (armagic != ARMAG) { armagic = fs16_to_host(UNIXFS_FS_BIG, magic); e = UNIXFS_FS_BIG; if (armagic != ARMAG) { err = EINVAL; fprintf(stderr, "%s is not an ar image file\n", dmg); goto out; } } sb = malloc(sizeof(struct super_block)); if (!sb) { err = ENOMEM; goto out; } assert(sizeof(struct filsys) <= BSIZE); fs = calloc(1, BSIZE); if (!fs) { free(sb); err = ENOMEM; goto out; } unixfs = sb; unixfs->s_flags = flags; unixfs->s_endian = (fse == UNIXFS_FS_INVALID) ? e : fse; unixfs->s_fs_info = (void*)fs; unixfs->s_bdev = fd; /* must initialize the inode layer before sanity checking */ if ((err = unixfs_inodelayer_init(sizeof(struct ar_node_info))) != 0) goto out; struct inode* rootip = unixfs_inodelayer_iget((ino_t)ROOTINO); if (!rootip) { fprintf(stderr, "*** fatal error: no root inode\n"); abort(); } rootip->I_mode = S_IFDIR | 0755; rootip->I_uid = getuid(); rootip->I_gid = getgid(); rootip->I_size = 2; rootip->I_atime_sec = rootip->I_mtime_sec = rootip->I_ctime_sec = time(0); struct ar_node_info* rootai = (struct ar_node_info*)rootip->I_private; rootai->ar_self = rootip; rootai->ar_name[0] = '\0'; rootai->ar_parent = NULL; rootai->ar_children = NULL; rootai->ar_next_sibling = NULL; unixfs_inodelayer_isucceeded(rootip); fs->s_fsize = (stbuf.st_size / BSIZE) + 1; fs->s_files = 0; fs->s_directories = 1 + 1 + 1; fs->s_rootip = rootip; fs->s_lastino = ROOTINO; char cnp[DIRSIZ + 1]; struct ar_hdr ar; ino_t parent_ino = ROOTINO; for (;;) { if (ancientfs_ar_readheader(fd, &ar) != 0) break; snprintf(cnp, DIRSIZ + 1, "%s", ar.ar_name); cnp[DIRSIZ] = '\0'; int missing = unixfs_internal_namei(parent_ino, cnp, &stbuf); if (!missing) /* duplicate */ goto next; struct inode* ip = unixfs_inodelayer_iget((ino_t)(fs->s_lastino + 1)); if (!ip) { fprintf(stderr, "*** fatal error: no inode for %llu\n", (ino64_t)(fs->s_lastino + 1)); abort(); } ip->I_mode = ancientfs_ar_mode(ar.ar_mode); ip->I_uid = ar.ar_uid; ip->I_gid = ar.ar_gid; ip->I_nlink = 1; ip->I_size = ar.ar_size; ip->I_atime_sec = ip->I_mtime_sec = ip->I_ctime_sec = ar.ar_date; struct ar_node_info* ai = (struct ar_node_info*)ip->I_private; ip->I_daddr[0] = (uint32_t)lseek(fd, (off_t)0, SEEK_CUR); memcpy(ai->ar_name, cnp, strlen(cnp)); ai->ar_self = ip; ai->ar_children = NULL; struct inode* parent_ip = unixfs_internal_iget(parent_ino); parent_ip->I_size += 1; ai->ar_parent = (struct ar_node_info*)(parent_ip->I_private); ai->ar_next_sibling = ai->ar_parent->ar_children; ai->ar_parent->ar_children = ai; if (S_ISDIR(ip->I_mode)) { fs->s_directories++; parent_ino = fs->s_lastino + 1; ip->I_size = 2; ip->I_daddr[0] = 0; } else { fs->s_files++; fs->s_lastino++; unixfs_internal_iput(parent_ip); unixfs_inodelayer_isucceeded(ip); /* no put */ } fs->s_lastino++; next: (void)lseek(fd, (off_t)(ar.ar_size + (ar.ar_size & 1)), SEEK_CUR); } unixfs->s_statvfs.f_bsize = BSIZE; unixfs->s_statvfs.f_frsize = BSIZE; unixfs->s_statvfs.f_ffree = 0; unixfs->s_statvfs.f_files = fs->s_files + fs->s_directories; unixfs->s_statvfs.f_blocks = fs->s_fsize; unixfs->s_statvfs.f_bfree = 0; unixfs->s_statvfs.f_bavail = 0; unixfs->s_dentsize = 1; unixfs->s_statvfs.f_namemax = DIRSIZ; snprintf(unixfs->s_fsname, UNIXFS_MNAMELEN, "UNIX Old ar"); char* dmg_basename = basename((char*)dmg); snprintf(unixfs->s_volname, UNIXFS_MAXNAMLEN, "%s (tape=%s)", unixfs_fstype, (dmg_basename) ? dmg_basename : "Archive Image"); *fsname = unixfs->s_fsname; *volname = unixfs->s_volname; out: if (err) { if (fd >= 0) close(fd); if (fs) free(fs); if (sb) free(sb); return NULL; } return sb; }
static void* unixfs_internal_init(const char* dmg, uint32_t flags, fs_endian_t fse, char** fsname, char** volname) { int fd = -1; if ((fd = open(dmg, O_RDONLY)) < 0) { perror("open"); return NULL; } int err, i, j; struct stat stbuf; struct super_block* sb = (struct super_block*)0; struct filsys* fs = (struct filsys*)0; uint32_t tapedir_begin_block = 0, tapedir_end_block = 0, last_block = 0; if ((err = fstat(fd, &stbuf)) != 0) { perror("fstat"); goto out; } if (!S_ISREG(stbuf.st_mode) && !(flags & UNIXFS_FORCE)) { err = EINVAL; fprintf(stderr, "%s is not a tape image file\n", dmg); goto out; } if (flags & ANCIENTFS_DECTAPE) { tapedir_begin_block = 0; tapedir_end_block = TAPEDIR_END_BLOCK_DEC; } else if (flags & ANCIENTFS_MAGTAPE) { tapedir_begin_block = 0; tapedir_end_block = TAPEDIR_END_BLOCK_MAG; } else if (flags & ANCIENTFS_GENTAPE) { tapedir_begin_block = 0; tapedir_end_block = TAPEDIR_END_BLOCK_GENERIC; } else { err = EINVAL; fprintf(stderr, "unrecognized tape type\n"); goto out; } if (S_ISREG(stbuf.st_mode)) last_block = stbuf.st_size / BSIZE; else last_block = tapedir_end_block; sb = malloc(sizeof(struct super_block)); if (!sb) { err = ENOMEM; goto out; } assert(sizeof(struct filsys) <= BSIZE); fs = calloc(1, BSIZE); if (!fs) { free(sb); err = ENOMEM; goto out; } unixfs = sb; unixfs->s_flags = flags; unixfs->s_endian = (fse == UNIXFS_FS_INVALID) ? UNIXFS_FS_PDP : fse; unixfs->s_fs_info = (void*)fs; unixfs->s_bdev = fd; /* must initialize the inode layer before sanity checking */ if ((err = unixfs_inodelayer_init(sizeof(struct tap_node_info))) != 0) goto out; struct inode* rootip = unixfs_inodelayer_iget((ino_t)ROOTINO); if (!rootip) { fprintf(stderr, "*** fatal error: no root inode\n"); abort(); } rootip->I_mode = S_IFDIR | 0755; rootip->I_uid = getuid(); rootip->I_gid = getgid(); rootip->I_size = 2; rootip->I_atime_sec = rootip->I_mtime_sec = rootip->I_ctime_sec = time(0); struct tap_node_info* rootti = (struct tap_node_info*)rootip->I_private; rootti->ti_self = rootip; rootti->ti_name[0] = '\0'; rootti->ti_parent = NULL; rootti->ti_children = NULL; rootti->ti_next_sibling = NULL; unixfs_inodelayer_isucceeded(rootip); fs->s_fsize = stbuf.st_size / BSIZE; fs->s_files = 0; fs->s_directories = 1 + 1 + 1; fs->s_rootip = rootip; fs->s_lastino = ROOTINO; char tapeblock[BSIZE]; for (i = tapedir_begin_block; i < tapedir_end_block; i++) { if (pread(fd, tapeblock, BSIZE, (off_t)(i * BSIZE)) != BSIZE) { fprintf(stderr, "*** fatal error: cannot read tape block %llu\n", (off_t)i); err = EIO; goto out; } struct dinode_dtp* di = (struct dinode_dtp*)tapeblock; int inopb = INOPB; if (i == 0) { /* special case block 0 */ uint8_t* doff = (uint8_t*)tapeblock; fs->s_dataoffset = 64 * (256 * doff[6] + doff[7]); di = (struct dinode_dtp*)((char*)tapeblock + 128); inopb--; } else if ((i * BSIZE) >= fs->s_dataoffset) { i = tapedir_end_block; j = inopb; break; } for (j = 0; j < inopb; j++, di++) { /* no checksum? */ if (!di->di_path[0]) { if (flags & ANCIENTFS_GENTAPE) { i = tapedir_end_block; j = inopb; } continue; } ino_t parent_ino = ROOTINO; char* path = (char*)di->di_path; size_t pathlen = strlen(path); if ((*path == '.') && ((pathlen == 1) || ((pathlen == 2) && (*(path + 1) == '/')))) { /* root */ rootip->I_mode = fs16_to_host(unixfs->s_endian, di->di_mode); rootip->I_atime_sec = \ rootip->I_mtime_sec = \ rootip->I_ctime_sec = \ fs32_to_host(unixfs->s_endian, di->di_mtime); continue; } /* we don't deal with many fancy paths here: just '/' and './' */ if (*path == '/') path++; else if (*path == '.' && *(path + 1) == '/') path += 2; char *cnp, *term; for (cnp = strtok_r(path, "/", &term); cnp; cnp = strtok_r(NULL, "/", &term)) { /* we have { parent_ino, cnp } */ struct stat stbuf; int missing = unixfs_internal_namei(parent_ino, cnp, &stbuf); if (!missing) { parent_ino = stbuf.st_ino; continue; } struct inode* ip = unixfs_inodelayer_iget((ino_t)(fs->s_lastino + 1)); if (!ip) { fprintf(stderr, "*** fatal error: no inode for %llu\n", (ino64_t)(fs->s_lastino + 1)); abort(); } ip->I_mode = fs16_to_host(unixfs->s_endian, di->di_mode); ip->I_uid = di->di_uid; ip->I_gid = di->di_gid; ip->I_size = di->di_size0 << 16 | fs16_to_host(unixfs->s_endian, di->di_size1); ip->I_daddr[0] = (uint32_t)fs16_to_host(unixfs->s_endian, di->di_addr); ip->I_nlink = 1; ip->I_atime_sec = ip->I_mtime_sec = ip->I_ctime_sec = fs32_to_host(unixfs->s_endian, di->di_mtime); struct tap_node_info* ti = (struct tap_node_info*)ip->I_private; memcpy(ti->ti_name, cnp, strlen(cnp)); ti->ti_self = ip; ti->ti_children = NULL; /* this should work out as long as we have no corruption */ struct inode* parent_ip = unixfs_internal_iget(parent_ino); parent_ip->I_size += 1; ti->ti_parent = (struct tap_node_info*)(parent_ip->I_private); ti->ti_next_sibling = ti->ti_parent->ti_children; ti->ti_parent->ti_children = ti; if (S_ISDIR(ancientfs_dtp_mode(ip->I_mode, flags))) { fs->s_directories++; parent_ino = fs->s_lastino + 1; ip->I_size = 2; ip->I_daddr[0] = 0; } else fs->s_files++; fs->s_lastino++; unixfs_internal_iput(parent_ip); unixfs_inodelayer_isucceeded(ip); /* no put */ } } } unixfs->s_statvfs.f_bsize = BSIZE; unixfs->s_statvfs.f_frsize = BSIZE; unixfs->s_statvfs.f_ffree = 0; unixfs->s_statvfs.f_files = fs->s_files + fs->s_directories; unixfs->s_statvfs.f_blocks = fs->s_fsize; unixfs->s_statvfs.f_bfree = 0; unixfs->s_statvfs.f_bavail = 0; unixfs->s_dentsize = 1; unixfs->s_statvfs.f_namemax = DIRSIZ; snprintf(unixfs->s_fsname, UNIXFS_MNAMELEN, "UNIX dtp"); char* dmg_basename = basename((char*)dmg); snprintf(unixfs->s_volname, UNIXFS_MAXNAMLEN, "%s (tape=%s)", unixfs_fstype, (dmg_basename) ? dmg_basename : "Tape Image"); *fsname = unixfs->s_fsname; *volname = unixfs->s_volname; out: if (err) { if (fd >= 0) close(fd); if (fs) free(fs); if (sb) free(sb); return NULL; } return sb; }
static void* unixfs_internal_init(const char* dmg, uint32_t flags, fs_endian_t fse, char** fsname, char** volname) { int fd = -1; if ((fd = open(dmg, O_RDONLY)) < 0) { perror("open"); return NULL; } int err; struct stat stbuf; struct super_block* sb = (struct super_block*)0; struct filsys* fs = (struct filsys*)0; if ((err = fstat(fd, &stbuf)) != 0) { perror("fstat"); goto out; } if (!S_ISREG(stbuf.st_mode) && !(flags & UNIXFS_FORCE)) { err = EINVAL; fprintf(stderr, "%s is not a tape image file\n", dmg); goto out; } struct cpio_newc_header hdr; if (read(fd, &hdr, sizeof(hdr)) != sizeof(hdr)) { fprintf(stderr, "failed to read data from file\n"); err = EIO; goto out; } char* magic = CPIO_NEWC_MAGIC; if (unixfs->s_flags & ANCIENTFS_NEWCRC) magic = CPIO_NEWCRC_MAGIC; if (strncmp(hdr.c_magic, magic, CPIO_NEWC_MAGLEN) != 0) { fprintf(stderr, "not recognized as a cpio_newc archive\n"); err = EINVAL; goto out; } sb = malloc(sizeof(struct super_block)); if (!sb) { err = ENOMEM; goto out; } assert(sizeof(struct filsys) <= CPIO_NEWC_BLOCK); fs = calloc(1, CPIO_NEWC_BLOCK); if (!fs) { free(sb); err = ENOMEM; goto out; } unixfs = sb; unixfs->s_flags = flags; /* not used */ unixfs->s_endian = (fse == UNIXFS_FS_INVALID) ? UNIXFS_FS_LITTLE : fse; unixfs->s_fs_info = (void*)fs; unixfs->s_bdev = fd; /* must initialize the inode layer before sanity checking */ if ((err = unixfs_inodelayer_init(sizeof(struct cpio_newc_node_info))) != 0) goto out; struct inode* rootip = unixfs_inodelayer_iget((ino_t)ROOTINO); if (!rootip) { fprintf(stderr, "*** fatal error: no root inode\n"); abort(); } rootip->I_mode = S_IFDIR | 0755; rootip->I_uid = getuid(); rootip->I_gid = getgid(); rootip->I_size = 2; rootip->I_atime_sec = rootip->I_mtime_sec = rootip->I_ctime_sec = time(0); struct cpio_newc_node_info* rootci = (struct cpio_newc_node_info*)rootip->I_private; rootci->ci_self = rootip; rootci->ci_parent = NULL; rootci->ci_children = NULL; rootci->ci_next_sibling = NULL; unixfs_inodelayer_isucceeded(rootip); fs->s_fsize = stbuf.st_size / CPIO_NEWC_BLOCK; fs->s_files = 0; fs->s_directories = 1 + 1 + 1; fs->s_rootip = rootip; fs->s_lastino = ROOTINO; lseek(fd, (off_t)0, SEEK_SET); /* rewind tape */ struct cpio_newc_entry _ce, *ce = &_ce; for (;;) { if ((err = ancientfs_cpio_newc_readheader(fd, ce)) != 0) { if (err == 1) break; else { fprintf(stderr, "*** fatal error: cannot read block (error %d)\n", err); err = EIO; goto out; } } char* path = ce->name; ino_t parent_ino = ROOTINO; size_t pathlen = strlen(ce->name); if ((*path == '.') && ((pathlen == 1) || ((pathlen == 2) && (*(path + 1) == '/')))) { /* root */ rootip->I_mode = ce->stat.st_mode; rootip->I_atime_sec = \ rootip->I_mtime_sec = \ rootip->I_ctime_sec = ce->stat.st_mtime; continue; } /* we don't deal with many fancy paths here: just '/' and './' */ if (*path == '/') path++; else if (*path == '.' && *(path + 1) == '/') path += 2; char *cnp, *term; for (cnp = strtok_r(path, "/", &term); cnp; cnp = strtok_r(NULL, "/", &term)) { /* we have { parent_ino, cnp } */ struct stat stbuf; int missing = unixfs_internal_namei(parent_ino, cnp, &stbuf); if (!missing) { parent_ino = stbuf.st_ino; if (!term) { /* out of order */ struct inode* dirp = unixfs_inodelayer_iget(parent_ino); if (!dirp || !dirp->I_initialized) { fprintf(stderr, "*** fatal error: inode %llu inconsistent\n", (ino64_t)parent_ino); abort(); } dirp->I_mode = ce->stat.st_mode; dirp->I_uid = ce->stat.st_uid; dirp->I_gid = ce->stat.st_gid; unixfs_inodelayer_iput(dirp); } continue; } struct inode* ip = unixfs_inodelayer_iget((ino_t)(fs->s_lastino + 1)); /* unixfs_inodelayer_iget(ce->stat.st_ino); */ if (!ip) { fprintf(stderr, "*** fatal error: no inode for %llu\n", (ino64_t)(fs->s_lastino + 1)); abort(); } ip->I_mode = ce->stat.st_mode; ip->I_uid = ce->stat.st_uid; ip->I_gid = ce->stat.st_gid; ip->I_size = ce->stat.st_size; ip->I_nlink = ce->stat.st_nlink; ip->I_rdev = ce->stat.st_rdev; ip->I_atime_sec = ip->I_mtime_sec = ip->I_ctime_sec = ce->stat.st_mtime; struct cpio_newc_node_info* ci = (struct cpio_newc_node_info*)ip->I_private; size_t namelen = strlen(cnp); ci->ci_name = malloc(namelen + 1); if (!ci->ci_name) { fprintf(stderr, "*** fatal error: cannot allocate memory\n"); abort(); } memcpy(ci->ci_name, cnp, namelen); ci->ci_name[namelen] = '\0'; ip->I_daddr[0] = 0; if (S_ISLNK(ip->I_mode)) { namelen = strlen(ce->linktargetname); ci->ci_linktargetname = malloc(namelen + 1); if (!ci->ci_name) { fprintf(stderr, "*** fatal error: cannot allocate memory\n"); abort(); } memcpy(ci->ci_linktargetname, ce->linktargetname, namelen); ci->ci_linktargetname[namelen] = '\0'; } else if (S_ISREG(ip->I_mode)) { ip->I_daddr[0] = ce->daddr; } ci->ci_self = ip; ci->ci_children = NULL; struct inode* parent_ip = unixfs_internal_iget(parent_ino); parent_ip->I_size += 1; ci->ci_parent = (struct cpio_newc_node_info*)(parent_ip->I_private); ci->ci_next_sibling = ci->ci_parent->ci_children; ci->ci_parent->ci_children = ci; if (term && !S_ISDIR(ip->I_mode)) /* out of order */ ip->I_mode = S_IFDIR | 0755; if (S_ISDIR(ip->I_mode)) { fs->s_directories++; parent_ino = fs->s_lastino + 1; /* parent_ino = ip->I_ino; */ ip->I_size = 2; } else fs->s_files++; fs->s_lastino++; /* if (ip->I_ino > fs->s_lastino) fs->s_lastino = ip->I_ino; */ unixfs_internal_iput(parent_ip); unixfs_inodelayer_isucceeded(ip); /* no put */ } /* for each component */ } /* for each block */ err = 0; unixfs->s_statvfs.f_bsize = CPIO_NEWC_BLOCK; unixfs->s_statvfs.f_frsize = CPIO_NEWC_BLOCK; unixfs->s_statvfs.f_ffree = 0; unixfs->s_statvfs.f_files = fs->s_files + fs->s_directories; unixfs->s_statvfs.f_blocks = fs->s_fsize; unixfs->s_statvfs.f_bfree = 0; unixfs->s_statvfs.f_bavail = 0; unixfs->s_dentsize = 1; unixfs->s_statvfs.f_namemax = UNIXFS_MAXNAMLEN; snprintf(unixfs->s_fsname, UNIXFS_MNAMELEN, "ASCII cpio (newc%s)", (unixfs->s_flags & ANCIENTFS_NEWCRC) ? "rc" : ""); char* dmg_basename = basename((char*)dmg); snprintf(unixfs->s_volname, UNIXFS_MAXNAMLEN, "%s (archive=%s)", unixfs_fstype, (dmg_basename) ? dmg_basename : "cpio_newc Image"); *fsname = unixfs->s_fsname; *volname = unixfs->s_volname; out: if (err) { if (fd >= 0) close(fd); if (fs) free(fs); if (sb) free(sb); return NULL; } return sb; }
unixfs_inodelayer_isucceeded(ip); } break; } } unixfs->s_statvfs.f_ffree = 0; unixfs->s_statvfs.f_files = fs->s_files + fs->s_directories; unixfs->s_statvfs.f_blocks = fs->s_fsize; unixfs->s_statvfs.f_bfree = 0; unixfs->s_statvfs.f_bavail = 0; unixfs->s_dentsize = DIRSIZ + 2; unixfs->s_statvfs.f_namemax = DIRSIZ; fs->s_rootip = unixfs_internal_iget(ROOTINO); if (!fs->s_rootip) { unixfs_internal_fini(fs); err = EINVAL; goto out; } fs->s_rootip->I_mtime_sec = fs->s_date; fs->s_rootip->I_ctime_sec = fs->s_ddate; unixfs_internal_iput(fs->s_rootip); snprintf(unixfs->s_fsname, UNIXFS_MNAMELEN, "UNIX dump/restor"); char* dmg_basename = basename((char*)dmg); snprintf(unixfs->s_volname, UNIXFS_MAXNAMLEN, "%s (tape=%s)", unixfs_fstype, (dmg_basename) ? dmg_basename : "Tape Image");
static int unixfs_internal_namei(ino_t parentino, const char* name, struct stat* stbuf) { if (parentino == OSXFUSE_ROOTINO) parentino = MINIX_ROOT_INO; stbuf->st_ino = ENOENT; struct inode* dir = unixfs_internal_iget(parentino); if (!dir) return ENOENT; if (!S_ISDIR(dir->I_mode)) { unixfs_internal_iput(dir); return ENOTDIR; } int ret = ENOENT; unsigned long namelen = strlen(name); unsigned long start, n; unsigned long npages = minix_dir_pages(dir); minix3_dirent* de3; minix_dirent* de; char page[PAGE_SIZE]; char* kaddr = NULL; struct super_block* sb = dir->I_sb; struct minix_sb_info* sbi = minix_sb(sb); unsigned chunk_size = sbi->s_dirsize; struct minix_inode_info* minix_inode = minix_i(dir); start = minix_inode->i_dir_start_lookup; if (start >= npages) start = 0; n = start; ino_t found_ino = 0; do { int error = minixfs_get_page(dir, n, page); if (!error) { kaddr = (char*)page; if (INODE_VERSION(dir) == MINIX_V3) { de3 = (minix3_dirent*)kaddr; kaddr += PAGE_CACHE_SIZE - chunk_size; for (; (char*)de3 <= kaddr; de3++) { if (!de3->inode) continue; if (minix_namecompare(namelen, chunk_size, name, de3->name)) { found_ino = de3->inode; goto found; } } } else { de = (minix_dirent*)kaddr; kaddr += PAGE_CACHE_SIZE - chunk_size; for (; (char*)de <= kaddr; de++) { if (!de->inode) continue; if (minix_namecompare(namelen, chunk_size, name, de->name)) { found_ino = de->inode; goto found; } } } } if (++n >= npages) n = 0; } while (n != start); found: if (found_ino) minix_inode->i_dir_start_lookup = n; unixfs_internal_iput(dir); if (found_ino) ret = unixfs_internal_igetattr(found_ino, stbuf); return ret; }