|
|
1.1 ! root 1: /* ! 2: * linux/fs/msdos/inode.c ! 3: * ! 4: * Written 1992 by Werner Almesberger ! 5: */ ! 6: ! 7: #include <linux/msdos_fs.h> ! 8: #include <linux/kernel.h> ! 9: #include <linux/sched.h> ! 10: #include <linux/errno.h> ! 11: #include <linux/string.h> ! 12: #include <linux/stat.h> ! 13: ! 14: #include <asm/segment.h> ! 15: ! 16: void msdos_put_inode(struct inode *inode) ! 17: { ! 18: struct inode *depend; ! 19: ! 20: inode->i_size = 0; ! 21: msdos_truncate(inode); ! 22: depend = (struct inode *) inode->i_data[D_DEPEND]; ! 23: memset(inode,0,sizeof(struct inode)); ! 24: if (depend) { ! 25: if ((struct inode *) depend->i_data[D_OLD] != inode) { ! 26: printk("Invalid link (0x%X): expected 0x%X, got " ! 27: "0x%X\r\n",(int) depend,(int) inode, ! 28: depend->i_data[D_OLD]); ! 29: panic("That's fatal"); ! 30: } ! 31: depend->i_data[D_OLD] = 0; ! 32: iput(depend); ! 33: } ! 34: } ! 35: ! 36: ! 37: void msdos_put_super(struct super_block *sb) ! 38: { ! 39: cache_inval_dev(sb->s_dev); ! 40: lock_super(sb); ! 41: sb->s_dev = 0; ! 42: free_super(sb); ! 43: return; ! 44: } ! 45: ! 46: ! 47: static struct super_operations msdos_sops = { ! 48: msdos_read_inode, ! 49: msdos_write_inode, ! 50: msdos_put_inode, ! 51: msdos_put_super, ! 52: NULL, /* added in 0.96c */ ! 53: msdos_statfs ! 54: }; ! 55: ! 56: ! 57: static int parse_options(char *options,char *check,char *conversion) ! 58: { ! 59: char *this,*value; ! 60: ! 61: *check = 'n'; ! 62: *conversion = 'b'; ! 63: if (!options) return 1; ! 64: for (this = strtok(options,","); this; this = strtok(NULL,",")) { ! 65: if (value = strchr(this,'=')) *value++ = 0; ! 66: if (!strcmp(this,"check") && value) { ! 67: if (value[0] && !value[1] && strchr("rns",*value)) ! 68: *check = *value; ! 69: else if (!strcmp(value,"relaxed")) *check = 'r'; ! 70: else if (!strcmp(value,"normal")) *check = 'n'; ! 71: else if (!strcmp(value,"strict")) *check = 's'; ! 72: else return 0; ! 73: } ! 74: else if (!strcmp(this,"conv") && value) { ! 75: if (value[0] && !value[1] && strchr("bta",*value)) ! 76: *conversion = *value; ! 77: else if (!strcmp(value,"binary")) *conversion = 'b'; ! 78: else if (!strcmp(value,"text")) *conversion = 't'; ! 79: else if (!strcmp(value,"auto")) *conversion = 'a'; ! 80: else return 0; ! 81: } ! 82: else return 0; ! 83: } ! 84: return 1; ! 85: } ! 86: ! 87: ! 88: /* Read the super block of an MS-DOS FS. */ ! 89: ! 90: struct super_block *msdos_read_super(struct super_block *s,void *data) ! 91: { ! 92: struct buffer_head *bh; ! 93: struct msdos_boot_sector *b; ! 94: int data_sectors; ! 95: char check,conversion; ! 96: ! 97: if (!parse_options((char *) data,&check,&conversion)) { ! 98: s->s_dev = 0; ! 99: return NULL; ! 100: } ! 101: cache_init(); ! 102: lock_super(s); ! 103: bh = bread(s->s_dev, 0, BLOCK_SIZE); ! 104: free_super(s); ! 105: if (bh == NULL) { ! 106: s->s_dev = 0; ! 107: printk("MSDOS bread failed\r\n"); ! 108: return NULL; ! 109: } ! 110: b = (struct msdos_boot_sector *) bh->b_data; ! 111: s->s_blocksize = 1024; /* we cannot handle anything else yet */ ! 112: MSDOS_SB(s)->cluster_size = b->cluster_size; ! 113: MSDOS_SB(s)->fats = b->fats; ! 114: MSDOS_SB(s)->fat_start = b->reserved; ! 115: MSDOS_SB(s)->fat_length = b->fat_length; ! 116: MSDOS_SB(s)->dir_start = b->reserved+b->fats*b->fat_length; ! 117: MSDOS_SB(s)->dir_entries = *((unsigned short *) &b->dir_entries); ! 118: MSDOS_SB(s)->data_start = MSDOS_SB(s)->dir_start+((MSDOS_SB(s)-> ! 119: dir_entries << 5) >> 9); ! 120: data_sectors = (*((unsigned short *) &b->sectors) ? *((unsigned short *) ! 121: &b->sectors) : b->total_sect)-MSDOS_SB(s)->data_start; ! 122: MSDOS_SB(s)->clusters = b->cluster_size ? data_sectors/b->cluster_size : ! 123: 0; ! 124: MSDOS_SB(s)->fat_bits = MSDOS_SB(s)->clusters > MSDOS_FAT12 ? 16 : 12; ! 125: brelse(bh); ! 126: printk("[MS-DOS FS Rel. alpha.6, FAT %d, check=%c, conv=%c]\r\n", ! 127: MSDOS_SB(s)->fat_bits,check,conversion); ! 128: printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,se=%d,ts=%d]\r\n", ! 129: b->media,MSDOS_SB(s)->cluster_size,MSDOS_SB(s)->fats,MSDOS_SB(s)->fat_start, ! 130: MSDOS_SB(s)->fat_length,MSDOS_SB(s)->dir_start,MSDOS_SB(s)->dir_entries, ! 131: MSDOS_SB(s)->data_start,*(unsigned short *) &b->sectors,b->total_sect); ! 132: if (!MSDOS_SB(s)->fats || (MSDOS_SB(s)->dir_entries & (MSDOS_DPS-1)) ! 133: || !b->cluster_size || MSDOS_SB(s)->clusters+2 > MSDOS_SB(s)-> ! 134: fat_length*SECTOR_SIZE*8/MSDOS_SB(s)->fat_bits) { ! 135: s->s_dev = 0; ! 136: printk("Unsupported FS parameters\r\n"); ! 137: return NULL; ! 138: } ! 139: if (!MSDOS_CAN_BMAP(MSDOS_SB(s))) printk("No bmap support\r\n"); ! 140: s->s_magic = MSDOS_SUPER_MAGIC; ! 141: MSDOS_SB(s)->name_check = check; ! 142: MSDOS_SB(s)->conversion = conversion; ! 143: /* set up enough so that it can read an inode */ ! 144: s->s_op = &msdos_sops; ! 145: MSDOS_SB(s)->fs_uid = current->uid; ! 146: MSDOS_SB(s)->fs_gid = current->gid; ! 147: MSDOS_SB(s)->fs_umask = current->umask; ! 148: if (!(s->s_mounted = iget(s->s_dev,MSDOS_ROOT_INO))) { ! 149: s->s_dev = 0; ! 150: printk("get root inode failed\n"); ! 151: return NULL; ! 152: } ! 153: return s; ! 154: } ! 155: ! 156: ! 157: void msdos_statfs(struct super_block *sb,struct statfs *buf) ! 158: { ! 159: int cluster_size,free,this; ! 160: ! 161: cluster_size = MSDOS_SB(sb)->cluster_size; ! 162: put_fs_long(sb->s_magic,&buf->f_type); ! 163: put_fs_long(SECTOR_SIZE,&buf->f_bsize); ! 164: put_fs_long(MSDOS_SB(sb)->clusters*cluster_size,&buf->f_blocks); ! 165: free = 0; ! 166: for (this = 2; this < MSDOS_SB(sb)->clusters+2; this++) ! 167: if (!fat_access(sb,this,-1)) free++; ! 168: free *= cluster_size; ! 169: put_fs_long(free,&buf->f_bfree); ! 170: put_fs_long(free,&buf->f_bavail); ! 171: put_fs_long(0,&buf->f_files); ! 172: put_fs_long(0,&buf->f_ffree); ! 173: } ! 174: ! 175: ! 176: int msdos_bmap(struct inode *inode,int block) ! 177: { ! 178: struct msdos_sb_info *sb; ! 179: int cluster,offset; ! 180: ! 181: sb = MSDOS_SB(inode->i_sb); ! 182: if ((sb->cluster_size & 1) || (sb->data_start & 1)) return 0; ! 183: if (inode->i_ino == MSDOS_ROOT_INO) { ! 184: if (sb->dir_start & 1) return 0; ! 185: return (sb->dir_start >> 1)+block; ! 186: } ! 187: cluster = (block*2)/sb->cluster_size; ! 188: offset = (block*2) % sb->cluster_size; ! 189: if (!(cluster = get_cluster(inode,cluster))) return 0; ! 190: return ((cluster-2)*sb->cluster_size+sb->data_start+offset) >> 1; ! 191: } ! 192: ! 193: ! 194: void msdos_read_inode(struct inode *inode) ! 195: { ! 196: struct buffer_head *bh; ! 197: struct msdos_dir_entry *raw_entry; ! 198: int this; ! 199: ! 200: /* printk("read inode %d\r\n",inode->i_ino); */ ! 201: inode->i_data[D_BUSY] = inode->i_data[D_DEPEND] = ! 202: inode->i_data[D_OLD] = 0; ! 203: inode->i_data[D_BINARY] = 1; ! 204: inode->i_uid = MSDOS_SB(inode->i_sb)->fs_uid; ! 205: inode->i_gid = MSDOS_SB(inode->i_sb)->fs_gid; ! 206: if (inode->i_ino == MSDOS_ROOT_INO) { ! 207: inode->i_mode = (0777 & ~MSDOS_SB(inode->i_sb)->fs_umask) | ! 208: S_IFDIR; ! 209: inode->i_op = &msdos_dir_inode_operations; ! 210: inode->i_nlink = 1; ! 211: inode->i_size = MSDOS_SB(inode->i_sb)->dir_entries* ! 212: sizeof(struct msdos_dir_entry); ! 213: inode->i_data[D_START] = 0; ! 214: inode->i_data[D_ATTRS] = 0; ! 215: inode->i_mtime = inode->i_atime = inode->i_ctime = 0; ! 216: return; ! 217: } ! 218: if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS, BLOCK_SIZE))) ! 219: panic("unable to read i-node block"); ! 220: raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) ! 221: [inode->i_ino & (MSDOS_DPB-1)]; ! 222: if (raw_entry->attr & ATTR_DIR) { ! 223: inode->i_mode = MSDOS_MKMODE(raw_entry->attr,0777 & ! 224: ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFDIR; ! 225: inode->i_op = &msdos_dir_inode_operations; ! 226: inode->i_nlink = 3; ! 227: inode->i_size = 0; ! 228: for (this = raw_entry->start; this && this != -1; this = ! 229: fat_access(inode->i_sb,this,-1)) ! 230: inode->i_size += SECTOR_SIZE*MSDOS_SB(inode->i_sb)-> ! 231: cluster_size; ! 232: } ! 233: else { ! 234: inode->i_mode = MSDOS_MKMODE(raw_entry->attr,0666 & ! 235: ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFREG; ! 236: inode->i_op = MSDOS_CAN_BMAP(MSDOS_SB(inode->i_sb)) ? ! 237: &msdos_file_inode_operations : ! 238: &msdos_file_inode_operations_no_bmap; ! 239: inode->i_nlink = 1; ! 240: inode->i_size = raw_entry->size; ! 241: } ! 242: inode->i_data[D_BINARY] = is_binary(MSDOS_SB(inode->i_sb)->conversion, ! 243: raw_entry->ext); ! 244: inode->i_data[D_START] = raw_entry->start; ! 245: inode->i_data[D_ATTRS] = raw_entry->attr & ATTR_UNUSED; ! 246: inode->i_mtime = inode->i_atime = inode->i_ctime = ! 247: date_dos2unix(raw_entry->time,raw_entry->date); ! 248: brelse(bh); ! 249: } ! 250: ! 251: ! 252: void msdos_write_inode(struct inode *inode) ! 253: { ! 254: struct buffer_head *bh; ! 255: struct msdos_dir_entry *raw_entry; ! 256: ! 257: inode->i_dirt = 0; ! 258: if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return; ! 259: if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS, BLOCK_SIZE))) ! 260: panic("unable to read i-node block"); ! 261: raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) ! 262: [inode->i_ino & (MSDOS_DPB-1)]; ! 263: if (S_ISDIR(inode->i_mode)) { ! 264: raw_entry->attr = ATTR_DIR; ! 265: raw_entry->size = 0; ! 266: } ! 267: else { ! 268: raw_entry->attr = ATTR_NONE; ! 269: raw_entry->size = inode->i_size; ! 270: } ! 271: raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) | inode->i_data[D_ATTRS]; ! 272: raw_entry->start = inode->i_data[D_START]; ! 273: date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date); ! 274: bh->b_dirt = 1; ! 275: brelse(bh); ! 276: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.