|
|
1.1 ! root 1: /* ! 2: * linux/fs/minix/file.c ! 3: * ! 4: * minix regular file handling primitives ! 5: */ ! 6: ! 7: #include <errno.h> ! 8: #include <fcntl.h> ! 9: ! 10: #include <sys/dirent.h> ! 11: #include <sys/stat.h> ! 12: ! 13: #include <asm/segment.h> ! 14: #include <asm/system.h> ! 15: ! 16: #include <linux/sched.h> ! 17: #include <linux/minix_fs.h> ! 18: #include <linux/kernel.h> ! 19: ! 20: #define NBUF 16 ! 21: ! 22: #define MIN(a,b) (((a)<(b))?(a):(b)) ! 23: #define MAX(a,b) (((a)>(b))?(a):(b)) ! 24: ! 25: #include <linux/fs.h> ! 26: #include <linux/minix_fs.h> ! 27: ! 28: int minix_file_read(struct inode *, struct file *, char *, int); ! 29: static int minix_file_write(struct inode *, struct file *, char *, int); ! 30: ! 31: /* ! 32: * We have mostly NULL's here: the current defaults are ok for ! 33: * the minix filesystem. ! 34: */ ! 35: static struct file_operations minix_file_operations = { ! 36: NULL, /* lseek - default */ ! 37: minix_file_read, /* read */ ! 38: minix_file_write, /* write */ ! 39: NULL, /* readdir - bad */ ! 40: NULL, /* select - default */ ! 41: NULL, /* ioctl - default */ ! 42: NULL, /* no special open is needed */ ! 43: NULL /* release */ ! 44: }; ! 45: ! 46: struct inode_operations minix_file_inode_operations = { ! 47: &minix_file_operations, /* default file operations */ ! 48: NULL, /* create */ ! 49: NULL, /* lookup */ ! 50: NULL, /* link */ ! 51: NULL, /* unlink */ ! 52: NULL, /* symlink */ ! 53: NULL, /* mkdir */ ! 54: NULL, /* rmdir */ ! 55: NULL, /* mknod */ ! 56: NULL, /* rename */ ! 57: NULL, /* readlink */ ! 58: NULL, /* follow_link */ ! 59: minix_bmap, /* bmap */ ! 60: minix_truncate /* truncate */ ! 61: }; ! 62: ! 63: static inline void wait_on_buffer(struct buffer_head * bh) ! 64: { ! 65: cli(); ! 66: while (bh->b_lock) ! 67: sleep_on(&bh->b_wait); ! 68: sti(); ! 69: } ! 70: ! 71: /* ! 72: * minix_file_read() is also needed by the directory read-routine, ! 73: * so it's not static. NOTE! reading directories directly is a bad idea, ! 74: * but has to be supported for now for compatability reasons with older ! 75: * versions. ! 76: */ ! 77: int minix_file_read(struct inode * inode, struct file * filp, char * buf, int count) ! 78: { ! 79: int read,left,chars,nr; ! 80: int block, blocks, offset; ! 81: struct buffer_head ** bhb, ** bhe; ! 82: struct buffer_head * buflist[NBUF]; ! 83: ! 84: if (!inode) { ! 85: printk("minix_file_read: inode = NULL\n"); ! 86: return -EINVAL; ! 87: } ! 88: if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode))) { ! 89: printk("minix_file_read: mode = %07o\n",inode->i_mode); ! 90: return -EINVAL; ! 91: } ! 92: if (filp->f_pos > inode->i_size) ! 93: left = 0; ! 94: else ! 95: left = inode->i_size - filp->f_pos; ! 96: if (left > count) ! 97: left = count; ! 98: if (left <= 0) ! 99: return 0; ! 100: read = 0; ! 101: block = filp->f_pos >> BLOCK_SIZE_BITS; ! 102: offset = filp->f_pos & (BLOCK_SIZE-1); ! 103: blocks = (left + offset + BLOCK_SIZE - 1) / BLOCK_SIZE; ! 104: bhb = bhe = buflist; ! 105: do { ! 106: if (blocks) { ! 107: --blocks; ! 108: if (nr = minix_bmap(inode,block++)) { ! 109: *bhb = getblk(inode->i_dev,nr); ! 110: if (!(*bhb)->b_uptodate) ! 111: ll_rw_block(READ,*bhb); ! 112: } else ! 113: *bhb = NULL; ! 114: ! 115: if (++bhb == &buflist[NBUF]) ! 116: bhb = buflist; ! 117: ! 118: if (bhb != bhe) ! 119: continue; ! 120: } ! 121: if (*bhe) { ! 122: wait_on_buffer(*bhe); ! 123: if (!(*bhe)->b_uptodate) { ! 124: do { ! 125: brelse(*bhe); ! 126: if (++bhe == &buflist[NBUF]) ! 127: bhe = buflist; ! 128: } while (bhe != bhb); ! 129: break; ! 130: } ! 131: } ! 132: ! 133: if (left < BLOCK_SIZE - offset) ! 134: chars = left; ! 135: else ! 136: chars = BLOCK_SIZE - offset; ! 137: filp->f_pos += chars; ! 138: left -= chars; ! 139: read += chars; ! 140: if (*bhe) { ! 141: memcpy_tofs(buf,offset+(*bhe)->b_data,chars); ! 142: brelse(*bhe); ! 143: buf += chars; ! 144: } else { ! 145: while (chars-->0) ! 146: put_fs_byte(0,buf++); ! 147: } ! 148: offset = 0; ! 149: if (++bhe == &buflist[NBUF]) ! 150: bhe = buflist; ! 151: } while (left > 0); ! 152: if (!read) ! 153: return -EIO; ! 154: inode->i_atime = CURRENT_TIME; ! 155: inode->i_dirt = 1; ! 156: return read; ! 157: } ! 158: ! 159: static int minix_file_write(struct inode * inode, struct file * filp, char * buf, int count) ! 160: { ! 161: off_t pos; ! 162: int written,block,c; ! 163: struct buffer_head * bh; ! 164: char * p; ! 165: ! 166: if (!inode) { ! 167: printk("minix_file_write: inode = NULL\n"); ! 168: return -EINVAL; ! 169: } ! 170: if (!S_ISREG(inode->i_mode)) { ! 171: printk("minix_file_write: mode = %07o\n",inode->i_mode); ! 172: return -EINVAL; ! 173: } ! 174: /* ! 175: * ok, append may not work when many processes are writing at the same time ! 176: * but so what. That way leads to madness anyway. ! 177: */ ! 178: if (filp->f_flags & O_APPEND) ! 179: pos = inode->i_size; ! 180: else ! 181: pos = filp->f_pos; ! 182: written = 0; ! 183: while (written<count) { ! 184: if (!(block = minix_create_block(inode,pos/BLOCK_SIZE))) { ! 185: if (!written) ! 186: written = -ENOSPC; ! 187: break; ! 188: } ! 189: c = BLOCK_SIZE - (pos % BLOCK_SIZE); ! 190: if (c > count-written) ! 191: c = count-written; ! 192: if (c == BLOCK_SIZE) ! 193: bh = getblk(inode->i_dev, block); ! 194: else ! 195: bh = bread(inode->i_dev,block); ! 196: if (!bh) { ! 197: if (!written) ! 198: written = -EIO; ! 199: break; ! 200: } ! 201: p = (pos % BLOCK_SIZE) + bh->b_data; ! 202: pos += c; ! 203: if (pos > inode->i_size) { ! 204: inode->i_size = pos; ! 205: inode->i_dirt = 1; ! 206: } ! 207: written += c; ! 208: memcpy_fromfs(p,buf,c); ! 209: buf += c; ! 210: bh->b_uptodate = 1; ! 211: bh->b_dirt = 1; ! 212: brelse(bh); ! 213: } ! 214: inode->i_mtime = CURRENT_TIME; ! 215: if (!(filp->f_flags & O_APPEND)) { ! 216: filp->f_pos = pos; ! 217: inode->i_ctime = CURRENT_TIME; ! 218: } ! 219: inode->i_dirt = 1; ! 220: return written; ! 221: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.