int readit(char *buffer, int count) { int logno, off, size; int cnt2, bnum2; struct fs *fs_copy; int n = 0; if (poff + count > inode.i_size) count = inode.i_size - poff; while (count > 0 && poff < inode.i_size) { fs_copy = fs; off = blkoff(fs_copy, poff); logno = lblkno(fs_copy, poff); cnt2 = size = blksize(fs_copy, &inode, logno); bnum2 = fsbtodb(fs_copy, block_map(logno)) + boff; if ( (!off) && (size <= count)) { devread(buffer, bnum2, cnt2); } else { size -= off; if (size > count) size = count; devread(iobuf, bnum2, cnt2); bcopy(iobuf+off, buffer, size); } buffer += size; count -= size; poff += size; n += size; } return n; }
static int ioread(void *addr, int count, int phys) { int logno, off, size; while (count) { off = blkoff(fs, poff); logno = lblkno(fs, poff); cnt = size = blksize(fs, &inode, logno); bnum = block_map(logno); if (bnum == -1) return(1); bnum = fsbtodb(fs, bnum) + boff; size -= off; if (size > count) size = count; if (disk_read(bnum, cnt, (vm_offset_t)iobuf)) return(1); if (phys) pcpy(iobuf+off,addr,size); else bcopy(iobuf+off,addr,size); addr = (char *)addr + size; count -= size; poff += size; } return(0); }
/* * Read a portion of a file into an internal buffer. * Return the location in the buffer and the amount in the buffer. */ static int buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) { struct file *fp = (struct file *)f->f_fsdata; struct fs *fs = fp->f_fs; long off; indp_t file_block; size_t block_size; int rc; off = ufs_blkoff(fs, fp->f_seekp); file_block = ufs_lblkno(fs, fp->f_seekp); #ifdef LIBSA_LFS block_size = dblksize(fs, &fp->f_di, file_block); #else block_size = ffs_sblksize(fs, (int64_t)fp->f_di.di_size, file_block); #endif if (file_block != fp->f_buf_blkno) { indp_t disk_block = 0; /* XXX: gcc */ rc = block_map(f, file_block, &disk_block); if (rc) return rc; if (disk_block == 0) { memset(fp->f_buf, 0, block_size); fp->f_buf_size = block_size; } else { twiddle(); rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, FSBTODB(fs, disk_block), block_size, fp->f_buf, &fp->f_buf_size); if (rc) return rc; } fp->f_buf_blkno = file_block; } /* * Return address of byte in buffer corresponding to * offset, and size of remainder of buffer after that * byte. */ *buf_p = fp->f_buf + off; *size_p = block_size - off; /* * But truncate buffer at end of file. */ if (*size_p > fp->f_di.di_size - fp->f_seekp) *size_p = fp->f_di.di_size - fp->f_seekp; return 0; }
/* * Read a portion of a file into an internal buffer. Return * the location in the buffer and the amount in the buffer. * * Parameters: * buf_p: out * size_p: out */ static int buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) { struct file *fp = (struct file *)f->f_fsdata; struct fs *fs = fp->f_fs; long off; daddr_t file_block; daddr_t disk_block; size_t block_size; int rc; off = blkoff(fs, fp->f_seekp); file_block = lblkno(fs, fp->f_seekp); block_size = dblksize(fs, &fp->f_di, file_block); if (file_block != fp->f_buf_blkno) { rc = block_map(f, file_block, &disk_block); if (rc) return (rc); if (fp->f_buf == NULL) fp->f_buf = malloc(fs->fs_bsize); if (disk_block == 0) { bzero(fp->f_buf, block_size); fp->f_buf_size = block_size; } else { twiddle(); rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, fsbtodb(fs, disk_block), block_size, fp->f_buf, &fp->f_buf_size); if (rc) return (rc); } fp->f_buf_blkno = file_block; } /* * Return address of byte in buffer corresponding to * offset, and size of remainder of buffer after that * byte. */ *buf_p = fp->f_buf + off; *size_p = block_size - off; /* * But truncate buffer at end of file. */ if (*size_p > fp->f_di.di_size - fp->f_seekp) *size_p = fp->f_di.di_size - fp->f_seekp; return (0); }
/* * Read a portion of a file into an internal buffer. * Return the location in the buffer and the amount in the buffer. */ static int buf_read_file(struct open_file *f, void *v, size_t *size_p) { char **buf_p = v; struct file *fp = (struct file *)f->f_fsdata; struct mfs_sblock *fs = fp->f_fs; long off; block_t file_block; block_t disk_block; size_t block_size; int rc; off = mfs_blkoff(fs, fp->f_seekp); file_block = mfs_lblkno(fs, fp->f_seekp); block_size = fs->mfs_block_size; if (file_block != fp->f_buf_blkno) { rc = block_map(f, file_block, &disk_block); if (rc) return rc; if (disk_block == 0) { memset(fp->f_buf, 0, block_size); fp->f_buf_size = block_size; } else { twiddle(); rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, FSBTODB(fs, disk_block), block_size, fp->f_buf, &fp->f_buf_size); if (rc) return rc; } fp->f_buf_blkno = file_block; } /* * Return address of byte in buffer corresponding to * offset, and size of remainder of buffer after that * byte. */ *buf_p = fp->f_buf + off; *size_p = block_size - off; /* * But truncate buffer at end of file. */ if (*size_p > fp->f_di.mdi_size - fp->f_seekp) *size_p = fp->f_di.mdi_size - fp->f_seekp; return 0; }
/* * Read a portion of a file into an internal buffer. * Return the location in the buffer and the amount in the buffer. */ static int buf_read_file(struct open_file *f, char **buf_p, size_t *size_p) { struct file *fp = (struct file *)f->f_fsdata; struct m_ext2fs *fs = fp->f_fs; long off; indp_t file_block; indp_t disk_block = 0; /* XXX: gcc */ size_t block_size; int rc; off = ext2_blkoff(fs, fp->f_seekp); file_block = ext2_lblkno(fs, fp->f_seekp); block_size = fs->e2fs_bsize; /* no fragment */ if (file_block != fp->f_buf_blkno) { rc = block_map(f, file_block, &disk_block); if (rc) return rc; if (disk_block == 0) { memset(fp->f_buf, 0, block_size); fp->f_buf_size = block_size; } else { twiddle(); rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, FSBTODB(fs, disk_block), block_size, fp->f_buf, &fp->f_buf_size); if (rc) return rc; } fp->f_buf_blkno = file_block; } /* * Return address of byte in buffer corresponding to * offset, and size of remainder of buffer after that * byte. */ *buf_p = fp->f_buf + off; *size_p = block_size - off; /* * But truncate buffer at end of file. */ /* XXX should handle LARGEFILE */ if (*size_p > fp->f_di.e2di_size - fp->f_seekp) *size_p = fp->f_di.e2di_size - fp->f_seekp; return 0; }
/* * Reads from a regular file. */ PUBLIC ssize_t file_read(struct inode *i, void *buf, size_t n, off_t off) { char *p; /* Writing pointer. */ size_t blkoff; /* Block offset. */ size_t chunk; /* Data chunk size. */ block_t blk; /* Working block number. */ struct buffer *bbuf; /* Working block buffer. */ p = buf; inode_lock(i); /* Read data. */ do { blk = block_map(i, off, 0); /* End of file reached. */ if (blk == BLOCK_NULL) goto out; bbuf = bread(i->dev, blk); blkoff = off % BLOCK_SIZE; /* Calculate read chunk size. */ chunk = (n < BLOCK_SIZE - blkoff) ? n : BLOCK_SIZE - blkoff; if ((off_t)chunk > i->size - off) { chunk = i->size - off; if (chunk == 0) { brelse(bbuf); goto out; } } kmemcpy(p, (char *)bbuf->data + blkoff, chunk); brelse(bbuf); n -= chunk; off += chunk; p += chunk; } while (n > 0); out: inode_touch(i); inode_unlock(i); return ((ssize_t)(p - (char *)buf)); }
/* * Writes to a regular file. */ PUBLIC ssize_t file_write(struct inode *i, const void *buf, size_t n, off_t off) { const char *p; /* Reading pointer. */ size_t blkoff; /* Block offset. */ size_t chunk; /* Data chunk size. */ block_t blk; /* Working block number. */ struct buffer *bbuf; /* Working block buffer. */ p = buf; inode_lock(i); /* Write data. */ do { blk = block_map(i, off, 1); /* End of file reached. */ if (blk == BLOCK_NULL) goto out; bbuf = bread(i->dev, blk); blkoff = off % BLOCK_SIZE; chunk = (n < BLOCK_SIZE - blkoff) ? n : BLOCK_SIZE - blkoff; kmemcpy((char *)bbuf->data + blkoff, buf, chunk); bbuf->flags |= BUFFER_DIRTY; brelse(bbuf); n -= chunk; off += chunk; p += chunk; /* Update file size. */ if (off > i->size) { i->size = off; i->flags |= INODE_DIRTY; } } while (n > 0); out: inode_touch(i); inode_unlock(i); return ((ssize_t)(p - (char *)buf)); }
static int find(char *path) { char *rest, ch; int block, off, loc, ino = ROOTINO; struct dirent *dp; char list_only; list_only = (path[0] == '?' && path[1] == '\0'); loop: devread(iobuf, fsbtodb(fs, ino_to_fsba(fs, ino)) + boff, fs->fs_bsize); bcopy((void *)&((struct dinode *)iobuf)[ino % fs->fs_inopb], (void *)&inode.i_din, sizeof (struct dinode)); if (!*path) return 1; while (*path == '/') path++; if (!inode.i_size || ((inode.i_mode&IFMT) != IFDIR)) return 0; for (rest = path; (ch = *rest) && ch != '/'; rest++) ; *rest = 0; loc = 0; do { if (loc >= inode.i_size) { if (list_only) { putchar('\n'); return -1; } else { return 0; } } if (!(off = blkoff(fs, loc))) { block = lblkno(fs, loc); devread(iobuf, fsbtodb(fs, block_map(block)) + boff, blksize(fs, &inode, block)); } dp = (struct dirent *)(iobuf + off); loc += dp->d_reclen; if (dp->d_fileno && list_only) { puts(dp->d_name); putchar(' '); } } while (!dp->d_fileno || strcmp(path, dp->d_name)); ino = dp->d_fileno; *(path = rest) = ch; goto loop; }
int find(const char *path) { const char *rest; int ch; int block, off, loc, ino = ROOTINO; struct dirent *dp; for (;;) { cnt = fs->fs_bsize; bnum = fsbtodb(fs,itod(fs,ino)) + boff; if (disk_read(bnum, cnt, (vm_offset_t)iobuf)) return 0; bcopy((char *)&((struct dinode *)iobuf)[ino % fs->fs_inopb], (char *)&inode.i_di, sizeof (struct dinode)); if (!*path) return 1; while (*path == '/') path++; if (!inode.i_size || ((inode.i_mode&IFMT) != IFDIR)) return 0; for (rest = path; (ch = *rest) && ch != '/'; rest++) ; loc = 0; for (;;) { if (loc >= inode.i_size) return 0; if (!(off = blkoff(fs, loc))) { block = lblkno(fs, loc); cnt = blksize(fs, &inode, block); bnum = fsbtodb(fs, block_map(block)) + boff; if (disk_read(bnum, cnt, (vm_offset_t)iobuf)) return 0; } dp = (struct dirent *)(iobuf + off); loc += dp->d_reclen; if (dp->d_ino == 0) continue; if (strncmp(path, dp->d_name, rest - path) == 0 && dp->d_name[rest - path] == 0) break; } ino = dp->d_ino; path = rest; } }
unsigned long ufs2_read (char *buf, unsigned long len, unsigned long write) { unsigned long logno, off, size, ret = 0; grub_int64_t map; while (len && !errnum) { off = blkoff (SUPERBLOCK, filepos); logno = lblkno (SUPERBLOCK, filepos); size = blksize (SUPERBLOCK, INODE_UFS2, logno); if ((map = block_map (logno)) < 0) break; size -= off; if (size > len) size = len; disk_read_func = disk_read_hook; devread (fsbtodb (SUPERBLOCK, map), off, size, buf, write); disk_read_func = NULL; if (buf) buf += size; len -= size; /* len always >= 0 */ filepos += size; ret += size; } if (errnum) ret = 0; return ret; }
int ufs2_read (char *buf, int len) { int logno, off, size, ret = 0; grub_int64_t map; while (len && !errnum) { off = blkoff (SUPERBLOCK, filepos); logno = lblkno (SUPERBLOCK, filepos); size = blksize (SUPERBLOCK, INODE_UFS2, logno); if ((map = block_map (logno)) < 0) break; size -= off; if (size > len) size = len; disk_read_func = disk_read_hook; devread (fsbtodb (SUPERBLOCK, map), off, size, buf); disk_read_func = NULL; buf += size; len -= size; filepos += size; ret += size; } if (errnum) ret = 0; return ret; }
/* * Open a file. */ __compactcall int ufs_open(const char *path, struct open_file *f) { #ifndef LIBSA_FS_SINGLECOMPONENT const char *cp, *ncp; int c; #endif ino32_t inumber; struct file *fp; struct fs *fs; int rc; #ifndef LIBSA_NO_FS_SYMLINK ino32_t parent_inumber; int nlinks = 0; char namebuf[MAXPATHLEN+1]; char *buf; #endif /* allocate file system specific data structure */ fp = alloc(sizeof(struct file)); memset(fp, 0, sizeof(struct file)); f->f_fsdata = (void *)fp; /* allocate space and read super block */ fs = alloc(SBLOCKSIZE); fp->f_fs = fs; twiddle(); #ifdef LIBSA_FFSv2 rc = ffs_find_superblock(f, fs); if (rc) goto out; #else { size_t buf_size; rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, SBLOCKOFFSET / DEV_BSIZE, SBLOCKSIZE, fs, &buf_size); if (rc) goto out; if (buf_size != SBLOCKSIZE || #ifdef LIBSA_FFS fs->lfs_version != REQUIRED_LFS_VERSION || #endif fs->fs_magic != FS_MAGIC) { rc = EINVAL; goto out; } } #if defined(LIBSA_LFS) && REQUIRED_LFS_VERSION == 2 /* * XXX We should check the second superblock and use the eldest * of the two. See comments near the top of lfs_mountfs() * in sys/ufs/lfs/lfs_vfsops.c. * This may need a LIBSA_LFS_SMALL check as well. */ #endif #endif #ifdef LIBSA_FFSv1 ffs_oldfscompat(fs); #endif if (fs->fs_bsize > MAXBSIZE || (size_t)fs->fs_bsize < sizeof(struct fs)) { rc = EINVAL; goto out; } /* * Calculate indirect block levels. */ { indp_t mult; int ln2; /* * We note that the number of indirect blocks is always * a power of 2. This lets us use shifts and masks instead * of divide and remainder and avoinds pulling in the * 64bit division routine into the boot code. */ mult = UFS_NINDIR(fs); #ifdef DEBUG if (mult & (mult - 1)) { /* Hummm was't a power of 2 */ rc = EINVAL; goto out; } #endif for (ln2 = 0; mult != 1; ln2++) mult >>= 1; fp->f_nishift = ln2; } /* alloc a block sized buffer used for all fs transfers */ fp->f_buf = alloc(fs->fs_bsize); inumber = UFS_ROOTINO; if ((rc = read_inode(inumber, f)) != 0) goto out; #ifndef LIBSA_FS_SINGLECOMPONENT cp = path; while (*cp) { /* * Remove extra separators */ while (*cp == '/') cp++; if (*cp == '\0') break; /* * Check that current node is a directory. */ if ((fp->f_di.di_mode & IFMT) != IFDIR) { rc = ENOTDIR; goto out; } /* * Get next component of path name. */ ncp = cp; while ((c = *cp) != '\0' && c != '/') cp++; /* * Look up component in current directory. * Save directory inumber in case we find a * symbolic link. */ #ifndef LIBSA_NO_FS_SYMLINK parent_inumber = inumber; #endif rc = search_directory(ncp, cp - ncp, f, &inumber); if (rc) goto out; /* * Open next component. */ if ((rc = read_inode(inumber, f)) != 0) goto out; #ifndef LIBSA_NO_FS_SYMLINK /* * Check for symbolic link. */ if ((fp->f_di.di_mode & IFMT) == IFLNK) { int link_len = fp->f_di.di_size; int len; len = strlen(cp); if (link_len + len > MAXPATHLEN || ++nlinks > MAXSYMLINKS) { rc = ENOENT; goto out; } memmove(&namebuf[link_len], cp, len + 1); if (link_len < fs->fs_maxsymlinklen) { memcpy(namebuf, fp->f_di.di_db, link_len); } else { /* * Read file for symbolic link */ size_t buf_size; indp_t disk_block; buf = fp->f_buf; rc = block_map(f, (indp_t)0, &disk_block); if (rc) goto out; twiddle(); rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, FSBTODB(fs, disk_block), fs->fs_bsize, buf, &buf_size); if (rc) goto out; memcpy(namebuf, buf, link_len); } /* * If relative pathname, restart at parent directory. * If absolute pathname, restart at root. */ cp = namebuf; if (*cp != '/') inumber = parent_inumber; else inumber = (ino32_t)UFS_ROOTINO; if ((rc = read_inode(inumber, f)) != 0) goto out; } #endif /* !LIBSA_NO_FS_SYMLINK */ } /* * Found terminal component. */ rc = 0; #else /* !LIBSA_FS_SINGLECOMPONENT */ /* look up component in the current (root) directory */ rc = search_directory(path, strlen(path), f, &inumber); if (rc) goto out; /* open it */ rc = read_inode(inumber, f); #endif /* !LIBSA_FS_SINGLECOMPONENT */ fp->f_seekp = 0; /* reset seek pointer */ out: if (rc) ufs_close(f); #ifdef FSMOD /* Only defined for lfs */ else fsmod = FSMOD; #endif return rc; }
/* * Open a file. */ static int ext2fs_open(const char *upath, struct open_file *f) { struct file *fp; struct ext2fs *fs; size_t buf_size; ino_t inumber, parent_inumber; int i, len, groups, bg_per_blk, blkgrps, mult; int nlinks = 0; int error = 0; char *cp, *ncp, *path = NULL, *buf = NULL; char namebuf[MAXPATHLEN+1]; char c; /* allocate file system specific data structure */ fp = malloc(sizeof(struct file)); if (fp == NULL) return (ENOMEM); bzero(fp, sizeof(struct file)); f->f_fsdata = (void *)fp; /* allocate space and read super block */ fs = (struct ext2fs *)malloc(sizeof(*fs)); fp->f_fs = fs; twiddle(); error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, EXT2_SBLOCK, EXT2_SBSIZE, (char *)fs, &buf_size); if (error) goto out; if (buf_size != EXT2_SBSIZE || fs->fs_magic != EXT2_MAGIC) { error = EINVAL; goto out; } /* * compute in-core values for the superblock */ fs->fs_bshift = EXT2_MINBSHIFT + fs->fs_fd.fd_bsize; fs->fs_bsize = 1 << fs->fs_bshift; fs->fs_bmask = fs->fs_bsize - 1; fs->fs_fshift = EXT2_MINFSHIFT + fs->fs_fd.fd_fsize; fs->fs_fsize = 1 << fs->fs_fshift; fs->fs_fmask = fs->fs_fsize - 1; if (fs->fs_revision == EXT2_REV0) { fs->fs_isize = EXT2_R0_ISIZE; fs->fs_firstino = EXT2_R0_FIRSTINO; } else { fs->fs_isize = fs->fs_fd.fd_isize; fs->fs_firstino = fs->fs_fd.fd_firstino; } fs->fs_imask = fs->fs_isize - 1; fs->fs_ipb = fs->fs_bsize / fs->fs_isize; fs->fs_fsbtodb = (fs->fs_bsize / DEV_BSIZE) - 1; /* * we have to load in the "group descriptors" here */ groups = howmany(fs->fs_blocks - fs->fs_firstblk, fs->fs_bpg); bg_per_blk = fs->fs_bsize / sizeof(struct ext2blkgrp); blkgrps = howmany(groups, bg_per_blk); len = blkgrps * fs->fs_bsize; fp->f_bg = malloc(len); twiddle(); error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, EXT2_SBLOCK + EXT2_SBSIZE / DEV_BSIZE, len, (char *)fp->f_bg, &buf_size); if (error) goto out; /* * XXX * validation of values? (blocksize, descriptors, etc?) */ /* * Calculate indirect block levels. */ mult = 1; for (i = 0; i < NIADDR; i++) { mult *= nindir(fs); fp->f_nindir[i] = mult; } inumber = EXT2_ROOTINO; if ((error = read_inode(inumber, f)) != 0) goto out; path = strdup(upath); if (path == NULL) { error = ENOMEM; goto out; } cp = path; while (*cp) { /* * Remove extra separators */ while (*cp == '/') cp++; if (*cp == '\0') break; /* * Check that current node is a directory. */ if (! S_ISDIR(fp->f_di.di_mode)) { error = ENOTDIR; goto out; } /* * Get next component of path name. */ len = 0; ncp = cp; while ((c = *cp) != '\0' && c != '/') { if (++len > EXT2_MAXNAMLEN) { error = ENOENT; goto out; } cp++; } *cp = '\0'; /* * Look up component in current directory. * Save directory inumber in case we find a * symbolic link. */ parent_inumber = inumber; error = search_directory(ncp, f, &inumber); *cp = c; if (error) goto out; /* * Open next component. */ if ((error = read_inode(inumber, f)) != 0) goto out; /* * Check for symbolic link. */ if (S_ISLNK(fp->f_di.di_mode)) { int link_len = fp->f_di.di_size; int len; len = strlen(cp); if (link_len + len > MAXPATHLEN || ++nlinks > MAXSYMLINKS) { error = ENOENT; goto out; } bcopy(cp, &namebuf[link_len], len + 1); if (fp->f_di.di_nblk == 0) { bcopy(fp->f_di.di_shortlink, namebuf, link_len); } else { /* * Read file for symbolic link */ struct ext2fs *fs = fp->f_fs; daddr_t disk_block; size_t buf_size; if (! buf) buf = malloc(fs->fs_bsize); error = block_map(f, (daddr_t)0, &disk_block); if (error) goto out; twiddle(); error = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, fsb_to_db(fs, disk_block), fs->fs_bsize, buf, &buf_size); if (error) goto out; bcopy((char *)buf, namebuf, link_len); } /* * If relative pathname, restart at parent directory. * If absolute pathname, restart at root. */ cp = namebuf; if (*cp != '/') inumber = parent_inumber; else inumber = (ino_t)EXT2_ROOTINO; if ((error = read_inode(inumber, f)) != 0) goto out; } } /* * Found terminal component. */ error = 0; out: if (buf) free(buf); if (path) free(path); if (error) { f->f_fsdata = NULL; if (fp->f_buf) free(fp->f_buf); free(fp->f_fs); free(fp); } return (error); }
/** * fsck_readi - same as libgfs2's gfs2_readi, but sets absolute block # * of the first bit of data read. */ static int fsck_readi(struct gfs2_inode *ip, void *rbuf, uint64_t roffset, unsigned int size, uint64_t *abs_block) { struct gfs2_sbd *sdp; struct gfs2_buffer_head *lbh; uint64_t lblock, dblock; unsigned int o; uint32_t extlen = 0; unsigned int amount; int not_new = 0; int isdir; int copied = 0; if (ip == NULL) return 0; sdp = ip->i_sbd; isdir = !!(S_ISDIR(ip->i_di.di_mode)); *abs_block = 0; if (roffset >= ip->i_di.di_size) return 0; if ((roffset + size) > ip->i_di.di_size) size = ip->i_di.di_size - roffset; if (!size) return 0; if (isdir) { o = roffset % sdp->sd_jbsize; lblock = roffset / sdp->sd_jbsize; } else { lblock = roffset >> sdp->sd_sb.sb_bsize_shift; o = roffset & (sdp->bsize - 1); } if (!ip->i_di.di_height) /* inode_is_stuffed */ o += sizeof(struct gfs2_dinode); else if (isdir) o += sizeof(struct gfs2_meta_header); while (copied < size) { amount = size - copied; if (amount > sdp->bsize - o) amount = sdp->bsize - o; if (!extlen) block_map(ip, lblock, ¬_new, &dblock, &extlen, FALSE); if (dblock) { lbh = bread(sdp, dblock); if (*abs_block == 0) *abs_block = lbh->b_blocknr; dblock++; extlen--; } else lbh = NULL; if (lbh) { memcpy(rbuf, lbh->b_data + o, amount); brelse(lbh); } else { memset(rbuf, 0, amount); } copied += amount; lblock++; o = (isdir) ? sizeof(struct gfs2_meta_header) : 0; } return copied; }
/* * Open a file. */ static int ufs_open(const char *upath, struct open_file *f) { char *cp, *ncp; int c; ino_t inumber, parent_inumber; struct file *fp; struct fs *fs; int rc; size_t buf_size; int nlinks = 0; char namebuf[MAXPATHLEN+1]; char *buf = NULL; char *path = NULL; /* allocate file system specific data structure */ fp = malloc(sizeof(struct file)); bzero(fp, sizeof(struct file)); f->f_fsdata = (void *)fp; /* allocate space and read super block */ fs = malloc(SBSIZE); fp->f_fs = fs; twiddle(); rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, SBOFF / DEV_BSIZE, SBSIZE, (char *)fs, &buf_size); if (rc) goto out; if (buf_size != SBSIZE || fs->fs_magic != FS_MAGIC || fs->fs_bsize > MAXBSIZE || fs->fs_bsize < sizeof(struct fs)) { rc = EINVAL; goto out; } #ifdef COMPAT_UFS ffs_oldfscompat(fs); #endif /* * Calculate indirect block levels. */ { int omult; int mult; int level; omult = 0; mult = 1; for (level = 0; level < NIADDR; level++) { mult *= NINDIR(fs); if (mult < omult) mult = 0x7FFFFFFF; fp->f_nindir[level] = mult; omult = mult; } } inumber = ROOTINO; if ((rc = read_inode(inumber, f)) != 0) goto out; cp = path = strdup(upath); if (path == NULL) { rc = ENOMEM; goto out; } while (*cp) { /* * Remove extra separators */ while (*cp == '/') cp++; if (*cp == '\0') break; /* * Check that current node is a directory. */ if ((fp->f_di.di_mode & IFMT) != IFDIR) { rc = ENOTDIR; goto out; } /* * Get next component of path name. */ { int len = 0; ncp = cp; while ((c = *cp) != '\0' && c != '/') { if (++len > MAXNAMLEN) { rc = ENOENT; goto out; } cp++; } *cp = '\0'; } /* * Look up component in current directory. * Save directory inumber in case we find a * symbolic link. */ parent_inumber = inumber; rc = search_directory(ncp, f, &inumber); *cp = c; if (rc) goto out; /* * Open next component. */ if ((rc = read_inode(inumber, f)) != 0) goto out; /* * Check for symbolic link. */ if ((fp->f_di.di_mode & IFMT) == IFLNK) { int link_len = fp->f_di.di_size; int len; len = strlen(cp); if (link_len + len > MAXPATHLEN || ++nlinks > MAXSYMLINKS) { rc = ENOENT; goto out; } bcopy(cp, &namebuf[link_len], len + 1); if (link_len < fs->fs_maxsymlinklen) { bcopy(fp->f_di.di_shortlink, namebuf, (unsigned) link_len); } else { /* * Read file for symbolic link */ size_t buf_size; daddr_t disk_block; struct fs *fs = fp->f_fs; if (!buf) buf = malloc(fs->fs_bsize); rc = block_map(f, (daddr_t)0, &disk_block); if (rc) goto out; twiddle(); rc = (f->f_dev->dv_strategy)(f->f_devdata, F_READ, fsbtodb(fs, disk_block), fs->fs_bsize, buf, &buf_size); if (rc) goto out; bcopy((char *)buf, namebuf, (unsigned)link_len); } /* * If relative pathname, restart at parent directory. * If absolute pathname, restart at root. */ cp = namebuf; if (*cp != '/') inumber = parent_inumber; else inumber = (ino_t)ROOTINO; if ((rc = read_inode(inumber, f)) != 0) goto out; } } /* * Found terminal component. */ fp->f_seekp = 0; rc = 0; out: if (buf) free(buf); if (path) free(path); if (rc) { f->f_fsdata = NULL; if (fp->f_buf) free(fp->f_buf); free(fp->f_fs); free(fp); } return (rc); }
/** * @brief Searches for a directory entry. * * @details Searches for a directory entry named @p filename in the directory * pointed to be @p dip. If @p create is not zero and such file entry * does not exist, the entry is created. * * @param dip Directory where the directory entry shall be searched. * @param filename Name of the directory entry that shall be searched. * @param buf Buffer where the directory entry is loaded. * @param create Create directory entry? * * @returns Upon successful completion, the directory entry is returned. In this * case, @p buf is set to point to the (locked) buffer associated to * the requested directory entry. However, upon failure, a #NULL * pointer is returned instead. * * @note @p dip must be locked. * @note @p filename must point to a valid location. * @note @p buf must point to a valid location */ PRIVATE struct d_dirent *dirent_search (struct inode *dip, const char *filename, struct buffer **buf, int create) { int i; /* Working directory entry index. */ int entry; /* Index of first free directory entry. */ block_t blk; /* Working block number. */ int nentries; /* Number of directory entries. */ struct d_dirent *d; /* Directory entry. */ nentries = dip->size/sizeof(struct d_dirent); /* Search from very first block. */ i = 0; entry = -1; blk = dip->blocks[0]; (*buf) = NULL; d = NULL; /* Search directory entry. */ while (i < nentries) { /* * Skip invalid blocks. As directory entries * are removed from a directory, a whole block * may become free. */ if (blk == BLOCK_NULL) { i += BLOCK_SIZE/sizeof(struct d_dirent); blk = block_map(dip, i*sizeof(struct d_dirent), 0); continue; } /* Get buffer. */ if ((*buf) == NULL) { (*buf) = bread(dip->dev, blk); d = (*buf)->data; } /* Get next block */ else if ((char *)d >= BLOCK_SIZE + (char *) (*buf)->data) { brelse((*buf)); (*buf) = NULL; blk = block_map(dip, i*sizeof(struct d_dirent), 0); continue; } /* Valid entry. */ if (d->d_ino != INODE_NULL) { /* Found */ if (!kstrncmp(d->d_name, filename, NAME_MAX)) { /* Duplicated entry. */ if (create) { brelse((*buf)); d = NULL; curr_proc->errno = EEXIST; } return (d); } } /* Remember entry index. */ else entry = i; d++; i++; } /* House keeping. */ if ((*buf) != NULL) { brelse((*buf)); (*buf) = NULL; } /* Create entry. */ if (create) { /* Expand directory. */ if (entry < 0) { entry = nentries; blk = block_map(dip, entry*sizeof(struct d_dirent), 1); /* Failed to create entry. */ if (blk == BLOCK_NULL) { curr_proc->errno = -ENOSPC; return (NULL); } dip->size += sizeof(struct d_dirent); inode_touch(dip); } else blk = block_map(dip, entry*sizeof(struct d_dirent), 0); (*buf) = bread(dip->dev, blk); entry %= (BLOCK_SIZE/sizeof(struct d_dirent)); d = &((struct d_dirent *)((*buf)->data))[entry]; return (d); } return (NULL); }
int ffs_dir (char *dirname) { char *rest, ch; int block, off, loc, map, ino = ROOTINO; struct direct *dp; /* main loop to find destination inode */ loop: /* load current inode (defaults to the root inode) */ if (!devread (fsbtodb (SUPERBLOCK, itod (SUPERBLOCK, ino)), ino % (SUPERBLOCK->fs_inopb) * sizeof (struct dinode), sizeof (struct dinode), (char *) INODE)) return 0; /* XXX what return value? */ /* if we have a real file (and we're not just printing possibilities), then this is where we want to exit */ if (!*dirname || isspace (*dirname)) { if ((INODE->i_mode & IFMT) != IFREG) { errnum = ERR_BAD_FILETYPE; return 0; } filemax = INODE->i_size; /* incomplete implementation requires this! */ fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize; return 1; } /* continue with file/directory name interpretation */ while (*dirname == '/') dirname++; if (!(INODE->i_size) || ((INODE->i_mode & IFMT) != IFDIR)) { errnum = ERR_BAD_FILETYPE; return 0; } for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); *rest = 0; loc = 0; /* loop for reading a the entries in a directory */ do { if (loc >= INODE->i_size) { #if 0 putchar ('\n'); #endif if (print_possibilities < 0) return 1; errnum = ERR_FILE_NOT_FOUND; *rest = ch; return 0; } if (!(off = blkoff (SUPERBLOCK, loc))) { block = lblkno (SUPERBLOCK, loc); if ((map = block_map (block)) < 0 || !devread (fsbtodb (SUPERBLOCK, map), 0, blksize (SUPERBLOCK, INODE, block), (char *) FSYS_BUF)) { errnum = ERR_FSYS_CORRUPT; *rest = ch; return 0; } } dp = (struct direct *) (FSYS_BUF + off); loc += dp->d_reclen; #ifndef STAGE1_5 if (dp->d_ino && print_possibilities && ch != '/' && (!*dirname || substring (dirname, dp->d_name) <= 0)) { if (print_possibilities > 0) print_possibilities = -print_possibilities; print_a_completion (dp->d_name); } #endif /* STAGE1_5 */ } while (!dp->d_ino || (substring (dirname, dp->d_name) != 0 || (print_possibilities && ch != '/'))); /* only get here if we have a matching directory entry */ ino = dp->d_ino; *(dirname = rest) = ch; /* go back to main loop at top of function */ goto loop; }
/* * Loads an ELF 32 executable. */ PRIVATE addr_t load_elf32(struct inode *inode) { int i; /* Loop index. */ addr_t addr; /* Region address. */ addr_t entry; /* Program entry point. */ struct elf32_fhdr *elf; /* ELF file header. */ struct elf32_phdr *seg; /* ELF Program header. */ block_t blk; /* Working block number. */ buffer_t header; /* File headers block buffer. */ struct region *reg; /* Working memory region. */ struct pregion *preg; /* Working process memory region. */ blk = block_map(inode, 0, 0); /* Empty file. */ if (blk == BLOCK_NULL) { curr_proc->errno = -ENOEXEC; return (0); } /* Read ELF file header. */ header = bread(inode->dev, blk); elf = buffer_data(header); /* Bad ELF file. */ if (!is_elf(elf)) { brelse(header); curr_proc->errno = -ENOEXEC; return (0); } /* Bad ELF file. */ if (elf->e_phoff + elf->e_phnum*elf->e_phentsize > BLOCK_SIZE) { brelse(header); curr_proc->errno = -ENOEXEC; return (0); } seg = (struct elf32_phdr *)((char *)buffer_data(header) + elf->e_phoff); /* Load segments. */ for (i = 0; i < elf->e_phnum; i++) { /* Not loadable. */ if (seg[i].p_type != PT_LOAD) continue; /* Broken executable. */ if (seg[i].p_filesz > seg[i].p_memsz) { kprintf("broken executable"); brelse(header); curr_proc->errno = -ENOEXEC; return (0); } addr = ALIGN(seg[i].p_vaddr, seg[i].p_align); /* Text section. */ if (!(seg[i].p_flags ^ (PF_R | PF_X))) { preg = TEXT(curr_proc); reg = allocreg(S_IRUSR | S_IXUSR, seg[i].p_memsz, 0); } /* Data section. */ else { preg = DATA(curr_proc); reg = allocreg(S_IRUSR | S_IWUSR, seg[i].p_memsz, 0); } /* Failed to allocate region. */ if (reg == NULL) { brelse(header); curr_proc->errno = -ENOMEM; return (0); } /* Attach memory region. */ if (attachreg(curr_proc, preg, addr, reg)) { freereg(reg); brelse(header); curr_proc->errno = -ENOMEM; return (0); } loadreg(inode, reg, seg[i].p_offset, seg[i].p_filesz); unlockreg(reg); } entry = elf->e_entry; brelse(header); return (entry); }
/* * Open a file. */ __compactcall int ext2fs_open(const char *path, struct open_file *f) { #ifndef LIBSA_FS_SINGLECOMPONENT const char *cp, *ncp; int c; #endif ino32_t inumber; struct file *fp; struct m_ext2fs *fs; int rc; #ifndef LIBSA_NO_FS_SYMLINK ino32_t parent_inumber; int nlinks = 0; char namebuf[MAXPATHLEN+1]; char *buf; #endif /* allocate file system specific data structure */ fp = alloc(sizeof(struct file)); memset(fp, 0, sizeof(struct file)); f->f_fsdata = (void *)fp; /* allocate space and read super block */ fs = alloc(sizeof(*fs)); memset(fs, 0, sizeof(*fs)); fp->f_fs = fs; twiddle(); rc = read_sblock(f, fs); if (rc) goto out; #ifdef EXT2FS_DEBUG dump_sblock(fs); #endif /* alloc a block sized buffer used for all fs transfers */ fp->f_buf = alloc(fs->e2fs_bsize); /* read group descriptor blocks */ fs->e2fs_gd = alloc(sizeof(struct ext2_gd) * fs->e2fs_ncg); rc = read_gdblock(f, fs); if (rc) goto out; /* * Calculate indirect block levels. */ { indp_t mult; int ln2; /* * We note that the number of indirect blocks is always * a power of 2. This lets us use shifts and masks instead * of divide and remainder and avoinds pulling in the * 64bit division routine into the boot code. */ mult = EXT2_NINDIR(fs); #ifdef DEBUG if (!powerof2(mult)) { /* Hummm was't a power of 2 */ rc = EINVAL; goto out; } #endif for (ln2 = 0; mult != 1; ln2++) mult >>= 1; fp->f_nishift = ln2; } inumber = EXT2_ROOTINO; if ((rc = read_inode(inumber, f)) != 0) goto out; #ifndef LIBSA_FS_SINGLECOMPONENT cp = path; while (*cp) { /* * Remove extra separators */ while (*cp == '/') cp++; if (*cp == '\0') break; /* * Check that current node is a directory. */ if ((fp->f_di.e2di_mode & EXT2_IFMT) != EXT2_IFDIR) { rc = ENOTDIR; goto out; } /* * Get next component of path name. */ ncp = cp; while ((c = *cp) != '\0' && c != '/') cp++; /* * Look up component in current directory. * Save directory inumber in case we find a * symbolic link. */ #ifndef LIBSA_NO_FS_SYMLINK parent_inumber = inumber; #endif rc = search_directory(ncp, cp - ncp, f, &inumber); if (rc) goto out; /* * Open next component. */ if ((rc = read_inode(inumber, f)) != 0) goto out; #ifndef LIBSA_NO_FS_SYMLINK /* * Check for symbolic link. */ if ((fp->f_di.e2di_mode & EXT2_IFMT) == EXT2_IFLNK) { /* XXX should handle LARGEFILE */ int link_len = fp->f_di.e2di_size; int len; len = strlen(cp); if (link_len + len > MAXPATHLEN || ++nlinks > MAXSYMLINKS) { rc = ENOENT; goto out; } memmove(&namebuf[link_len], cp, len + 1); if (link_len < EXT2_MAXSYMLINKLEN) { memcpy(namebuf, fp->f_di.e2di_blocks, link_len); } else { /* * Read file for symbolic link */ size_t buf_size; indp_t disk_block; buf = fp->f_buf; rc = block_map(f, (indp_t)0, &disk_block); if (rc) goto out; twiddle(); rc = DEV_STRATEGY(f->f_dev)(f->f_devdata, F_READ, FSBTODB(fs, disk_block), fs->e2fs_bsize, buf, &buf_size); if (rc) goto out; memcpy(namebuf, buf, link_len); } /* * If relative pathname, restart at parent directory. * If absolute pathname, restart at root. */ cp = namebuf; if (*cp != '/') inumber = parent_inumber; else inumber = (ino32_t)EXT2_ROOTINO; if ((rc = read_inode(inumber, f)) != 0) goto out; } #endif /* !LIBSA_NO_FS_SYMLINK */ } /* * Found terminal component. */ rc = 0; #else /* !LIBSA_FS_SINGLECOMPONENT */ /* look up component in the current (root) directory */ rc = search_directory(path, strlen(path), f, &inumber); if (rc) goto out; /* open it */ rc = read_inode(inumber, f); #endif /* !LIBSA_FS_SINGLECOMPONENT */ fp->f_seekp = 0; /* reset seek pointer */ out: if (rc) ext2fs_close(f); else fsmod = "ext2fs"; return rc; }
int ufs2_dir (char *dirname) { char *rest, ch; unsigned long block, off, loc, ino = ROOTINO; grub_int64_t map; struct direct *dp; int j, k; char ch1; #ifdef GRUB_UTIL char tmp_name[512]; #else char *tmp_name = (char *)(NAME_BUF); /* MAXNAMLEN is 255, so 512 byte buffer is needed. */ #endif /* main loop to find destination inode */ loop: /* load current inode (defaults to the root inode) */ if (!devread (fsbtodb (SUPERBLOCK, ino_to_fsba (SUPERBLOCK, ino)), ino % (SUPERBLOCK->fs_inopb) * sizeof (struct ufs2_dinode), sizeof (struct ufs2_dinode), (char *) INODE_UFS2, 0xedde0d90)) return 0; /* XXX what return value? */ /* if we have a real file (and we're not just printing possibilities), then this is where we want to exit */ if (!*dirname || isspace (*dirname)) { if ((INODE_UFS2->di_mode & IFMT) != IFREG) { errnum = ERR_BAD_FILETYPE; return 0; } filemax = INODE_UFS2->di_size; /* incomplete implementation requires this! */ fsmax = (NDADDR + NINDIR (SUPERBLOCK)) * SUPERBLOCK->fs_bsize; return 1; } /* continue with file/directory name interpretation */ while (*dirname == '/') dirname++; if (!(INODE_UFS2->di_size) || ((INODE_UFS2->di_mode & IFMT) != IFDIR)) { errnum = ERR_BAD_FILETYPE; return 0; } //for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++); for (rest = dirname; (ch = *rest) && !isspace (ch) && ch != '/'; rest++) { if (ch == '\\') { rest++; if (! (ch = *rest)) break; } } *rest = 0; loc = 0; /* loop for reading a the entries in a directory */ do { if (loc >= INODE_UFS2->di_size) { if (print_possibilities < 0) return 1; errnum = ERR_FILE_NOT_FOUND; *rest = ch; return 0; } if (!(off = blkoff (SUPERBLOCK, loc))) { block = lblkno (SUPERBLOCK, loc); if ((map = block_map (block)) < 0 || !devread (fsbtodb (SUPERBLOCK, map), 0, blksize (SUPERBLOCK, INODE_UFS2, block), (char *) FSYS_BUF, 0xedde0d90)) { errnum = ERR_FSYS_CORRUPT; *rest = ch; return 0; } } dp = (struct direct *) (FSYS_BUF + off); loc += dp->d_reclen; /* copy dp->name to tmp_name, and quote the spaces with a '\\' */ for (j = 0, k = 0; j < dp->d_namlen; j++) { if (! (ch1 = dp->d_name[j])) break; if (ch1 == ' ') tmp_name[k++] = '\\'; tmp_name[k++] = ch1; } tmp_name[k] = 0; #ifndef STAGE1_5 if (dp->d_ino && print_possibilities && ch != '/' && (!*dirname || substring (dirname, tmp_name, 0) <= 0)) { if (print_possibilities > 0) print_possibilities = -print_possibilities; print_a_completion (tmp_name); } #endif /* STAGE1_5 */ } while (!dp->d_ino || (substring (dirname, dp->d_name, 0) != 0 || (print_possibilities && ch != '/'))); /* only get here if we have a matching directory entry */ ino = dp->d_ino; *(dirname = rest) = ch; /* go back to main loop at top of function */ goto loop; }