📄 cdfs_gnodeops.c
字号:
#ifndef lintstatic char *sccsid = "@(#)cdfs_gnodeops.c 4.1 (ULTRIX) 11/9/90";#endif lint/************************************************************************ * * * Copyright (c) 1986, 1987 by * * Digital Equipment Corporation, Maynard, MA * * All rights reserved. * * * * This software is furnished under a license and may be used and * * copied only in accordance with the terms of such license and * * with the inclusion of the above copyright notice. This * * software or any other copies thereof may not be provided or * * otherwise made available to any other person. No title to and * * ownership of the software is hereby transferred. * * * * This software is derived from software received from the * * University of California, Berkeley, and from Bell * * Laboratories. Use, duplication, or disclosure is subject to * * restrictions under license agreements with University of * * California and with AT&T. * * * * The information in this software is subject to change without * * notice and should not be construed as a commitment by Digital * * Equipment Corporation. * * * * Digital assumes no responsibility for the use or reliability * * of its software on equipment which is not supplied by Digital. * * * ************************************************************************//************************************************************************ * Modification History * fs/cdfs/cdfs_gnodeops.c * * 9-Nov-90 -- prs * Initial creation. * ***********************************************************************/#include "../h/param.h"#include "../h/systm.h"#include "../h/dir.h"#include "../h/user.h"#include "../h/gnode_common.h" #include "../h/gnode.h"#include "../h/proc.h"#include "../fs/cdfs/cdfs_fs.h"#include "../fs/cdfs/cdfs_inode.h"#include "../fs/cdfs/cdfs_mount.h"#include "../h/fs_types.h"#include "../h/conf.h"#include "../h/buf.h"#include "../h/mount.h"#include "../h/file.h"#include "../h/text.h"#include "../h/uio.h"#include "../h/ioctl.h"#include "../h/devio.h"#include "../h/tty.h"#include "../h/cmap.h"#include "../h/stat.h"#include "../h/kernel.h"#include "../h/kmalloc.h"/* * Don't cache blocks in non-executable files with the sticky bit * set. Used to keep swap files from cluttering up the data cache. */extern int kernel_locking; /* Sys-V locking: default is kernel */ /* kernel == 1; daemon == 0 */extern isodebug;cdfs_rwgp(gp, uio, rw, ioflag, cred) register struct gnode *gp; register struct uio *uio; enum uio_rw rw; int ioflag; struct ucred *cred;{ dev_t dev = (dev_t)gp->g_rdev; struct buf *bp; daddr_t lbn, bn; int error = 0; int bsize; int rasize, rablock; int raoffset; /* Not used */ int datainbuf, offinbuf; struct fs *fs; if (isodebug) { printf("cdfs_rwgp: gp 0x%x uio 0x%x cred 0x%x count = %d\n", gp, uio,cred,uio->uio_resid); } /* * If nothing to read...... */ if (uio->uio_resid == 0) return (0); if (uio->uio_offset >= gp->g_size) return(0); dev = gp->g_dev; fs = FS(gp); bsize = ISOFS_LBS(fs); do { if (uio->uio_offset >= gp->g_size) break; lbn = uio->uio_offset / bsize; bn = cdfs_ibmap(gp, lbn, &datainbuf, &offinbuf); if (gp->g_size - (uio->uio_offset + datainbuf) > 0) { rablock = cdfs_ibmap(gp, (uio->uio_offset + datainbuf) / bsize, &rasize, &raoffset); } else { rablock = 0; } offinbuf += (uio->uio_offset % bsize); datainbuf -= (uio->uio_offset % bsize); datainbuf = MIN(datainbuf, gp->g_size - uio->uio_offset); datainbuf = MIN(datainbuf, uio->uio_resid); if (datainbuf <= 0) break; if (rablock) bp = breada(dev, bn, fs->fs_ibsize, rablock, fs->fs_ibsize, (struct gnode *)NULL); else bp = bread(dev, bn, fs->fs_ibsize, (struct gnode *)NULL); if (bp->b_flags & B_ERROR) { error = EIO; brelse(bp); goto bad; } u.u_error = uiomove(bp->b_un.b_addr+offinbuf, datainbuf, rw, uio); brelse(bp); } while (u.u_error == 0 && uio->uio_resid > 0); if (error == 0) /* XXX */ error = u.u_error; /* XXX */bad: return (error);}cdfs_fcntl(gp, cmd, arg, flag, cred) register struct gnode *gp; register int cmd; register caddr_t arg; register int flag; struct ucred *cred;{ register int fmt = gp->g_mode & GFMT; dev_t dev; switch (fmt) { case GFREG: case GFDIR: if (cmd == FIONREAD) { *(off_t *)arg = gp->g_size - flag; return (0); } if (cmd == FIONBIO || cmd == FIOASYNC || cmd == FIOSINUSE || cmd == FIOCINUSE) /* XXX */ return (0); /* XXX */ /* fall into ... */ default: return (ENOTTY); }}cdfs_select(gp, rw, cred) register struct gnode *gp; register int rw; struct ucred *cred;{ return (1); /* XXX */}cdfs_close(gp, flag) register struct gnode *gp; register int flag;{ return;}cdfs_open(gp, mode) register struct gnode *gp; register int mode;{ return (0);}cdfs_symlink(ndp, target_name) register struct nameidata *ndp; register char *target_name;{ return (u.u_error = EROFS);}cdfs_readlink(gp, auio) register struct gnode *gp; register struct uio *auio;{ return (u.u_error = EOPNOTSUPP);}cdfs_stat(gp, sb) register struct gnode *gp; register struct stat *sb;{ /* * Copy from gnode table */ sb->st_dev = gp->g_dev; sb->st_ino = gp->g_number; sb->st_mode = gp->g_mode; sb->st_nlink = gp->g_nlink; sb->st_uid = gp->g_uid; sb->st_gid = gp->g_gid; sb->st_rdev = (dev_t)gp->g_rdev; sb->st_size = gp->g_size; sb->st_atime = gp->g_atime.tv_sec; sb->st_spare1 = gp->g_atime.tv_usec; sb->st_mtime = gp->g_mtime.tv_sec; sb->st_spare2 = gp->g_mtime.tv_usec; sb->st_ctime = gp->g_ctime.tv_sec; sb->st_spare3 = gp->g_ctime.tv_usec; sb->st_blksize = MAXBSIZE; sb->st_blocks = gp->g_size / sb->st_blksize; sb->st_gennum = gp->g_gennum; sb->st_spare4 = 0; return (0);}struct fs_data *cdfs_getfsdata(mp) register struct mount *mp;{ register struct fs_data *fs_data = mp->m_fs_data; register struct fs *fs; int blk; fs = (struct fs *) mp->m_bufp->b_un.b_addr; if (fs->fs_format == ISO_9660) { blk = ((int)fs->fs_block.isofs.iso_vol_space_size_lsb * ISOFS_LBS(fs)) / 1024; fs_data->fd_gtot = (int)fs->fs_block.isofs.iso_path_tbl_size_lsb; fs_data->fd_btot = ((int)fs->fs_block.isofs.iso_vol_space_size_lsb* (int)ISOFS_LBS(fs)) / 1024; } else { blk = ((int)fs->fs_block.hsgfs.iso_vol_space_size_lsb * ISOFS_LBS(fs)) / 1024; fs_data->fd_gtot = (int)fs->fs_block.hsgfs.iso_path_tbl_size_lsb; fs_data->fd_btot = ((int)fs->fs_block.hsgfs.iso_vol_space_size_lsb* (int)ISOFS_LBS(fs)) / 1024; } fs_data->fd_gfree = 0; fs_data->fd_bfree = 0; fs_data->fd_otsize = MAXBSIZE; fs_data->fd_mtsize = MAXBSIZE; fs_data->fd_bfreen = 0; fs_data->fd_dev = mp->m_dev; fs_data->fd_fstype = GT_CDFS; return(fs_data);}cdfs_getdirent(gp, uio, cred) register struct gnode *gp; register struct uio *uio; register struct ucred *cred;{ dev_t dev = (dev_t)gp->g_rdev; struct buf *bp; struct fs *fs; daddr_t bn; int error = 0; int dirblkstotransfer; int lbs, lbn; struct iso_dir *tmp_iso_dir; struct hsg_dir *tmp_hsg_dir; struct gen_dir *gen_dir; union { unsigned char incoming[4]; unsigned int outgoing; } iso_convert_int; unsigned int ubuf_size; unsigned int isodir_reclen; unsigned int isodir_offset; unsigned int offinbuf; int iso_secsize_resid; int rablock, rasize; int wasdot; unsigned int diskaddr; int datainbuf, tsize; int isiso; int skip_file; if (isodebug) { printf("cdfs_getdirent: gp 0x%x uio 0x%x cred 0x%x count = %d\n", gp, uio, cred, uio->uio_resid); } KM_ALLOC(gen_dir, struct gen_dir *, ISO_SECSIZE, KM_TEMP, KM_NOARG); fs = FS(gp); if (fs->fs_format == ISO_9660) isiso = 1; else isiso = 0; /* * If nothing to read...... */ if (uio->uio_resid == 0) { KM_FREE(gen_dir, KM_TEMP); return (0); } lbs = ISOFS_LBS(fs); ubuf_size = (uio->uio_resid / ISO_SECSIZE) * ISO_SECSIZE; isodir_offset = uio->uio_offset; if (isodir_offset % ISO_SECSIZE) { if (isodebug) printf("cdfs_getdirent: request not on a ISO_SECSIZE bound\n"); isodir_offset = (isodir_offset / ISO_SECSIZE) * ISO_SECSIZE; } /* * Set dirblkstotransfer to number of directory blocks which will * fit in the users buffer. */ dirblkstotransfer = ubuf_size / ISO_SECSIZE; if (dirblkstotransfer <= 0) { error = EINVAL; if (isodebug) printf("cdfs_getdirent: dirblkstotransfer = %d\n", dirblkstotransfer); goto out; } /* * Set dirblkstotransfer to the minimum of the number of directory * blocks that would fit into the user buffer, and the number of * directory blocks left to read in the directory. */ dirblkstotransfer = MIN(dirblkstotransfer, (gp->g_size - isodir_offset) / ISO_SECSIZE); if (isodebug) printf("cdfs_getdirent: dirblkstotransfer = %d\n", dirblkstotransfer); /* * If there is nothing left to transfer, just return. */ if (dirblkstotransfer == 0) { KM_FREE(gen_dir, KM_TEMP); return(0); } if (isodebug) { if (gp->g_number % ISO_SECSIZE) { printf("cdfs_getdirentries: gnode number %d (dir) does not start on a sector boundary\n", gp->g_number); KM_FREE(gen_dir, KM_TEMP); return(0); } } dev = gp->g_dev; diskaddr = ((unsigned int)G_TO_DIR(gp)->iso_dir_extent + (unsigned int)G_TO_DIR(gp)->iso_dir_xar) * lbs; do { lbn = isodir_offset / ISOFS_LBS(fs); /*
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -