root/fs/fat/inode.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. fat_put_inode
  2. fat_put_super
  3. parse_options
  4. fat_read_super
  5. fat_statfs
  6. fat_bmap
  7. is_exec
  8. fat_read_inode
  9. fat_write_inode
  10. fat_notify_change
  11. init_module
  12. cleanup_module

   1 /*
   2  *  linux/fs/fat/inode.c
   3  *
   4  *  Written 1992,1993 by Werner Almesberger
   5  *  VFAT extensions by Gordon Chaffee, merged with msdos fs by Henrik Storner
   6  */
   7 
   8 #define __NO_VERSION__
   9 #include <linux/module.h>
  10 
  11 #include <linux/msdos_fs.h>
  12 #include <linux/kernel.h>
  13 #include <linux/sched.h>
  14 #include <linux/errno.h>
  15 #include <linux/string.h>
  16 #include <linux/major.h>
  17 #include <linux/blkdev.h>
  18 #include <linux/fs.h>
  19 #include <linux/stat.h>
  20 #include <linux/locks.h>
  21 
  22 #include "msbuffer.h"
  23 #include "tables.h"
  24 
  25 #include <asm/segment.h>
  26 
  27 
  28 
  29 void fat_put_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
  30 {
  31         struct inode *depend;
  32         struct super_block *sb;
  33 
  34         if (inode->i_nlink) {
  35                 if (MSDOS_I(inode)->i_busy) fat_cache_inval_inode(inode);
  36                 return;
  37         }
  38         inode->i_size = 0;
  39         fat_truncate(inode);
  40         depend = MSDOS_I(inode)->i_depend;
  41         sb = inode->i_sb;
  42         clear_inode(inode);
  43         if (depend) {
  44                 if (MSDOS_I(depend)->i_old != inode) {
  45                         printk("Invalid link (0x%p): expected 0x%p, got 0x%p\n",
  46                             depend, inode, MSDOS_I(depend)->i_old);
  47                         fat_fs_panic(sb,"...");
  48                         return;
  49                 }
  50                 MSDOS_I(depend)->i_old = NULL;
  51                 iput(depend);
  52         }
  53 }
  54 
  55 
  56 void fat_put_super(struct super_block *sb)
     /* [previous][next][first][last][top][bottom][index][help] */
  57 {
  58         fat_cache_inval_dev(sb->s_dev);
  59         set_blocksize (sb->s_dev,BLOCK_SIZE);
  60         lock_super(sb);
  61         sb->s_dev = 0;
  62         unlock_super(sb);
  63         MOD_DEC_USE_COUNT;
  64         return;
  65 }
  66 
  67 
  68 static int parse_options(char *options,int *fat, int *blksize, int *debug,
     /* [previous][next][first][last][top][bottom][index][help] */
  69                          struct fat_mount_options *opts)
  70 {
  71         char *this_char,*value;
  72 
  73         opts->name_check = 'n';
  74         opts->conversion = 'b';
  75         opts->fs_uid = current->uid;
  76         opts->fs_gid = current->gid;
  77         opts->fs_umask = current->fs->umask;
  78         opts->quiet = opts->sys_immutable = opts->dotsOK = opts->showexec = opts->isvfat = 0;
  79         *debug = *fat = 0;
  80 
  81         if (!options) return 1;
  82         for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) {
  83                 if ((value = strchr(this_char,'=')) != NULL)
  84                         *value++ = 0;
  85                 if (!strcmp(this_char,"check") && value) {
  86                         if (value[0] && !value[1] && strchr("rns",*value))
  87                                 opts->name_check = *value;
  88                         else if (!strcmp(value,"relaxed")) opts->name_check = 'r';
  89                         else if (!strcmp(value,"normal")) opts->name_check = 'n';
  90                         else if (!strcmp(value,"strict")) opts->name_check = 's';
  91                         else return 0;
  92                 }
  93                 else if (!strcmp(this_char,"conv") && value) {
  94                         if (value[0] && !value[1] && strchr("bta",*value))
  95                                 opts->conversion = *value;
  96                         else if (!strcmp(value,"binary")) opts->conversion = 'b';
  97                         else if (!strcmp(value,"text")) opts->conversion = 't';
  98                         else if (!strcmp(value,"auto")) opts->conversion = 'a';
  99                         else return 0;
 100                 }
 101                 else if (!strcmp(this_char,"dots")) {
 102                         opts->dotsOK = 1;
 103                 }
 104                 else if (!strcmp(this_char,"nodots")) {
 105                         opts->dotsOK = 0;
 106                 }
 107                 else if (!strcmp(this_char,"showexec")) {
 108                         opts->showexec = 1;
 109                 }
 110                 else if (!strcmp(this_char,"dotsOK") && value) {
 111                         if (!strcmp(value,"yes")) opts->dotsOK = 1;
 112                         else if (!strcmp(value,"no")) opts->dotsOK = 0;
 113                         else return 0;
 114                 }
 115                 else if (!strcmp(this_char,"uid")) {
 116                         if (!value || !*value)
 117                                 return 0;
 118                         opts->fs_uid = simple_strtoul(value,&value,0);
 119                         if (*value)
 120                                 return 0;
 121                 }
 122                 else if (!strcmp(this_char,"gid")) {
 123                         if (!value || !*value)
 124                                 return 0;
 125                         opts->fs_gid = simple_strtoul(value,&value,0);
 126                         if (*value)
 127                                 return 0;
 128                 }
 129                 else if (!strcmp(this_char,"umask")) {
 130                         if (!value || !*value)
 131                                 return 0;
 132                         opts->fs_umask = simple_strtoul(value,&value,8);
 133                         if (*value)
 134                                 return 0;
 135                 }
 136                 else if (!strcmp(this_char,"debug")) {
 137                         if (value) return 0;
 138                         *debug = 1;
 139                 }
 140                 else if (!strcmp(this_char,"fat")) {
 141                         if (!value || !*value)
 142                                 return 0;
 143                         *fat = simple_strtoul(value,&value,0);
 144                         if (*value || (*fat != 12 && *fat != 16))
 145                                 return 0;
 146                 }
 147                 else if (!strcmp(this_char,"quiet")) {
 148                         if (value) return 0;
 149                         opts->quiet = 1;
 150                 }
 151                 else if (!strcmp(this_char,"blocksize")) {
 152                         *blksize = simple_strtoul(value,&value,0);
 153                         if (*value)
 154                                 return 0;
 155                         if (*blksize != 512 && *blksize != 1024){
 156                                 printk ("MSDOS FS: Invalid blocksize (512 or 1024)\n");
 157                         }
 158                 }
 159                 else if (!strcmp(this_char,"sys_immutable")) {
 160                         if (value)
 161                                 return 0;
 162                         opts->sys_immutable = 1;
 163                 }
 164         }
 165         return 1;
 166 }
 167 
 168 
 169 /* Read the super block of an MS-DOS FS. */
 170 
 171 struct super_block *fat_read_super(struct super_block *sb,void *data, int silent)
     /* [previous][next][first][last][top][bottom][index][help] */
 172 {
 173         struct buffer_head *bh;
 174         struct msdos_boot_sector *b;
 175         int data_sectors,logical_sector_size,sector_mult,fat_clusters=0;
 176         int debug,error,fat;
 177         int blksize = 512;
 178         struct fat_mount_options opts;
 179 
 180         MOD_INC_USE_COUNT;
 181         if (hardsect_size[MAJOR(sb->s_dev)] != NULL){
 182                 blksize = hardsect_size[MAJOR(sb->s_dev)][MINOR(sb->s_dev)];
 183                 if (blksize != 512){
 184                         printk ("MSDOS: Hardware sector size is %d\n",blksize);
 185                 }
 186         }
 187         if (!parse_options((char *) data, &fat, &blksize, &debug, &opts)
 188                 || (blksize != 512 && blksize != 1024)) {
 189                 sb->s_dev = 0;
 190                 MOD_DEC_USE_COUNT;
 191                 return NULL;
 192         }
 193         cache_init();
 194         lock_super(sb);
 195         /* The first read is always 1024 bytes */
 196         sb->s_blocksize = 1024;
 197         set_blocksize(sb->s_dev, 1024);
 198         bh = bread(sb->s_dev, 0, 1024);
 199         unlock_super(sb);
 200         if (bh == NULL || !fat_is_uptodate(sb,bh)) {
 201                 brelse (bh);
 202                 sb->s_dev = 0;
 203                 printk("FAT bread failed\n");
 204                 MOD_DEC_USE_COUNT;
 205                 return NULL;
 206         }
 207         b = (struct msdos_boot_sector *) bh->b_data;
 208         set_blocksize(sb->s_dev, blksize);
 209 /*
 210  * The DOS3 partition size limit is *not* 32M as many people think.  
 211  * Instead, it is 64K sectors (with the usual sector size being
 212  * 512 bytes, leading to a 32M limit).
 213  * 
 214  * DOS 3 partition managers got around this problem by faking a 
 215  * larger sector size, ie treating multiple physical sectors as 
 216  * a single logical sector.
 217  * 
 218  * We can accommodate this scheme by adjusting our cluster size,
 219  * fat_start, and data_start by an appropriate value.
 220  *
 221  * (by Drew Eckhardt)
 222  */
 223 
 224 #define ROUND_TO_MULTIPLE(n,m) ((n) && (m) ? (n)+(m)-1-((n)-1)%(m) : 0)
 225     /* don't divide by zero */
 226 
 227         logical_sector_size = CF_LE_W(*(unsigned short *) &b->sector_size);
 228         sector_mult = logical_sector_size >> SECTOR_BITS;
 229         MSDOS_SB(sb)->cluster_size = b->cluster_size*sector_mult;
 230         MSDOS_SB(sb)->fats = b->fats;
 231         MSDOS_SB(sb)->fat_start = CF_LE_W(b->reserved)*sector_mult;
 232         MSDOS_SB(sb)->fat_length = CF_LE_W(b->fat_length)*sector_mult;
 233         MSDOS_SB(sb)->dir_start = (CF_LE_W(b->reserved)+b->fats*CF_LE_W(
 234             b->fat_length))*sector_mult;
 235         MSDOS_SB(sb)->dir_entries = CF_LE_W(*((unsigned short *) &b->dir_entries
 236             ));
 237         MSDOS_SB(sb)->data_start = MSDOS_SB(sb)->dir_start+ROUND_TO_MULTIPLE((
 238             MSDOS_SB(sb)->dir_entries << MSDOS_DIR_BITS) >> SECTOR_BITS,
 239             sector_mult);
 240         data_sectors = (CF_LE_W(*((unsigned short *) &b->sectors)) ?
 241             CF_LE_W(*((unsigned short *) &b->sectors)) :
 242             CF_LE_L(b->total_sect))*sector_mult-MSDOS_SB(sb)->data_start;
 243         error = !b->cluster_size || !sector_mult;
 244         if (!error) {
 245                 MSDOS_SB(sb)->clusters = b->cluster_size ? data_sectors/
 246                     b->cluster_size/sector_mult : 0;
 247                 MSDOS_SB(sb)->fat_bits = fat ? fat : MSDOS_SB(sb)->clusters >
 248                     MSDOS_FAT12 ? 16 : 12;
 249                 fat_clusters = MSDOS_SB(sb)->fat_length*SECTOR_SIZE*8/
 250                     MSDOS_SB(sb)->fat_bits;
 251                 error = !MSDOS_SB(sb)->fats || (MSDOS_SB(sb)->dir_entries &
 252                     (MSDOS_DPS-1)) || MSDOS_SB(sb)->clusters+2 > fat_clusters+
 253                     MSDOS_MAX_EXTRA || (logical_sector_size & (SECTOR_SIZE-1))
 254                     || !b->secs_track || !b->heads;
 255         }
 256         brelse(bh);
 257         /*
 258                 This must be done after the brelse because the bh is a dummy
 259                 allocated by fat_bread (see buffer.c)
 260         */
 261         sb->s_blocksize = blksize;      /* Using this small block size solve the */
 262                                 /* the misfit with buffer cache and cluster */
 263                                 /* because cluster (DOS) are often aligned */
 264                                 /* on odd sector */
 265         sb->s_blocksize_bits = blksize == 512 ? 9 : 10;
 266         if (error || debug) {
 267                 /* The MSDOS_CAN_BMAP is obsolete, but left just to remember */
 268                 printk("[MS-DOS FS Rel. 12,FAT %d,check=%c,conv=%c,"
 269                        "uid=%d,gid=%d,umask=%03o%s]\n",
 270                        MSDOS_SB(sb)->fat_bits,opts.name_check,
 271                        opts.conversion,opts.fs_uid,opts.fs_gid,opts.fs_umask,
 272                        MSDOS_CAN_BMAP(MSDOS_SB(sb)) ? ",bmap" : "");
 273                 printk("[me=0x%x,cs=%d,#f=%d,fs=%d,fl=%d,ds=%d,de=%d,data=%d,"
 274                        "se=%d,ts=%ld,ls=%d]\n",b->media,MSDOS_SB(sb)->cluster_size,
 275                        MSDOS_SB(sb)->fats,MSDOS_SB(sb)->fat_start,MSDOS_SB(sb)->fat_length,
 276                        MSDOS_SB(sb)->dir_start,MSDOS_SB(sb)->dir_entries,
 277                        MSDOS_SB(sb)->data_start,
 278                        CF_LE_W(*(unsigned short *) &b->sectors),
 279                        (unsigned long)b->total_sect,logical_sector_size);
 280                 printk ("Transaction block size = %d\n",blksize);
 281         }
 282         if (MSDOS_SB(sb)->clusters+2 > fat_clusters)
 283                 MSDOS_SB(sb)->clusters = fat_clusters-2;
 284         if (error) {
 285                 if (!silent)
 286                         printk("VFS: Can't find a valid MSDOS filesystem on dev "
 287                                "%s.\n", kdevname(sb->s_dev));
 288                 sb->s_dev = 0;
 289                 MOD_DEC_USE_COUNT;
 290                 return NULL;
 291         }
 292         sb->s_magic = MSDOS_SUPER_MAGIC;
 293         /* set up enough so that it can read an inode */
 294         MSDOS_SB(sb)->free_clusters = -1; /* don't know yet */
 295         MSDOS_SB(sb)->fat_wait = NULL;
 296         MSDOS_SB(sb)->fat_lock = 0;
 297         MSDOS_SB(sb)->prev_free = 0;
 298         memcpy(&(MSDOS_SB(sb)->options), &opts, sizeof(struct fat_mount_options));
 299         if (!(sb->s_mounted = iget(sb,MSDOS_ROOT_INO))) {
 300                 sb->s_dev = 0;
 301                 printk("get root inode failed\n");
 302                 MOD_DEC_USE_COUNT;
 303                 return NULL;
 304         }
 305         return sb;
 306 }
 307 
 308 
 309 void fat_statfs(struct super_block *sb,struct statfs *buf, int bufsiz)
     /* [previous][next][first][last][top][bottom][index][help] */
 310 {
 311         int free,nr;
 312         struct statfs tmp;
 313 
 314         lock_fat(sb);
 315         if (MSDOS_SB(sb)->free_clusters != -1)
 316                 free = MSDOS_SB(sb)->free_clusters;
 317         else {
 318                 free = 0;
 319                 for (nr = 2; nr < MSDOS_SB(sb)->clusters+2; nr++)
 320                         if (!fat_access(sb,nr,-1)) free++;
 321                 MSDOS_SB(sb)->free_clusters = free;
 322         }
 323         unlock_fat(sb);
 324         tmp.f_type = sb->s_magic;
 325         tmp.f_bsize = MSDOS_SB(sb)->cluster_size*SECTOR_SIZE;
 326         tmp.f_blocks = MSDOS_SB(sb)->clusters;
 327         tmp.f_bfree = free;
 328         tmp.f_bavail = free;
 329         tmp.f_files = 0;
 330         tmp.f_ffree = 0;
 331         tmp.f_namelen = 12;
 332         memcpy_tofs(buf, &tmp, bufsiz);
 333 }
 334 
 335 
 336 int fat_bmap(struct inode *inode,int block)
     /* [previous][next][first][last][top][bottom][index][help] */
 337 {
 338         struct msdos_sb_info *sb;
 339         int cluster,offset;
 340 
 341         sb = MSDOS_SB(inode->i_sb);
 342         if (inode->i_ino == MSDOS_ROOT_INO) {
 343                 return sb->dir_start + block;
 344         }
 345         cluster = block/sb->cluster_size;
 346         offset = block % sb->cluster_size;
 347         if (!(cluster = get_cluster(inode,cluster))) return 0;
 348         return (cluster-2)*sb->cluster_size+sb->data_start+offset;
 349 }
 350 
 351 static int is_exec(char *extension)
     /* [previous][next][first][last][top][bottom][index][help] */
 352 {
 353         char *exe_extensions = "EXECOMBAT", *walk;
 354 
 355         for (walk = exe_extensions; *walk; walk += 3)
 356                 if (!strncmp(extension, walk, 3))
 357                         return 1;
 358         return 0;
 359 }
 360 
 361 void fat_read_inode(struct inode *inode, struct inode_operations *fs_dir_inode_ops)
     /* [previous][next][first][last][top][bottom][index][help] */
 362 {
 363         struct super_block *sb = inode->i_sb;
 364         struct buffer_head *bh;
 365         struct msdos_dir_entry *raw_entry;
 366         int nr;
 367 
 368 /* printk("read inode %d\n",inode->i_ino); */
 369         MSDOS_I(inode)->i_busy = 0;
 370         MSDOS_I(inode)->i_depend = MSDOS_I(inode)->i_old = NULL;
 371         MSDOS_I(inode)->i_binary = 1;
 372         inode->i_uid = MSDOS_SB(inode->i_sb)->options.fs_uid;
 373         inode->i_gid = MSDOS_SB(inode->i_sb)->options.fs_gid;
 374         inode->i_version = ++event;
 375         if (inode->i_ino == MSDOS_ROOT_INO) {
 376                 inode->i_mode = (S_IRWXUGO & ~MSDOS_SB(inode->i_sb)->options.fs_umask) |
 377                     S_IFDIR;
 378                 inode->i_op = fs_dir_inode_ops;
 379                 inode->i_nlink = fat_subdirs(inode)+2;
 380                     /* subdirs (neither . nor ..) plus . and "self" */
 381                 inode->i_size = MSDOS_SB(inode->i_sb)->dir_entries*
 382                     sizeof(struct msdos_dir_entry);
 383                 inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*
 384                     SECTOR_SIZE;
 385                 inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
 386                     inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
 387                 MSDOS_I(inode)->i_start = 0;
 388                 MSDOS_I(inode)->i_attrs = 0;
 389                 inode->i_mtime = inode->i_atime = inode->i_ctime = 0;
 390                 return;
 391         }
 392         if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS,
 393             SECTOR_SIZE))) {
 394                 printk("dev = %s, ino = %ld\n",
 395                        kdevname(inode->i_dev), inode->i_ino);
 396                 panic("fat_read_inode: unable to read i-node block");
 397         }
 398         raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
 399             [inode->i_ino & (MSDOS_DPB-1)];
 400         if ((raw_entry->attr & ATTR_DIR) && !IS_FREE(raw_entry->name)) {
 401                 inode->i_mode = MSDOS_MKMODE(raw_entry->attr,S_IRWXUGO &
 402                     ~MSDOS_SB(inode->i_sb)->options.fs_umask) | S_IFDIR;
 403                 inode->i_op = fs_dir_inode_ops;
 404 
 405                 MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
 406                 inode->i_nlink = fat_subdirs(inode);
 407                     /* includes .., compensating for "self" */
 408 #ifdef DEBUG
 409                 if (!inode->i_nlink) {
 410                         printk("directory %d: i_nlink == 0\n",inode->i_ino);
 411                         inode->i_nlink = 1;
 412                 }
 413 #endif
 414                 inode->i_size = 0;
 415                 if ((nr = CF_LE_W(raw_entry->start)) != 0)
 416                         while (nr != -1) {
 417                                 inode->i_size += SECTOR_SIZE*MSDOS_SB(inode->
 418                                     i_sb)->cluster_size;
 419                                 if (!(nr = fat_access(inode->i_sb,nr,-1))) {
 420                                         printk("Directory %ld: bad FAT\n",
 421                                             inode->i_ino);
 422                                         break;
 423                                 }
 424                         }
 425         } else { /* not a directory */
 426                 inode->i_mode = MSDOS_MKMODE(raw_entry->attr,
 427                     ((IS_NOEXEC(inode) || 
 428                       (MSDOS_SB(inode->i_sb)->options.showexec &&
 429                        !is_exec(raw_entry->ext)))
 430                         ? S_IRUGO|S_IWUGO : S_IRWXUGO)
 431                     & ~MSDOS_SB(inode->i_sb)->options.fs_umask) | S_IFREG;
 432                 inode->i_op = (sb->s_blocksize == 1024)
 433                         ? &fat_file_inode_operations_1024
 434                         : &fat_file_inode_operations;
 435                 MSDOS_I(inode)->i_start = CF_LE_W(raw_entry->start);
 436                 inode->i_nlink = 1;
 437                 inode->i_size = CF_LE_L(raw_entry->size);
 438         }
 439         if(raw_entry->attr & ATTR_SYS)
 440                 if (MSDOS_SB(inode->i_sb)->options.sys_immutable)
 441                         inode->i_flags |= S_IMMUTABLE;
 442         MSDOS_I(inode)->i_binary = is_binary(MSDOS_SB(inode->i_sb)->options.conversion,
 443             raw_entry->ext);
 444         MSDOS_I(inode)->i_attrs = raw_entry->attr & ATTR_UNUSED;
 445         /* this is as close to the truth as we can get ... */
 446         inode->i_blksize = MSDOS_SB(inode->i_sb)->cluster_size*SECTOR_SIZE;
 447         inode->i_blocks = (inode->i_size+inode->i_blksize-1)/
 448             inode->i_blksize*MSDOS_SB(inode->i_sb)->cluster_size;
 449         inode->i_mtime = inode->i_atime =
 450             date_dos2unix(CF_LE_W(raw_entry->time),CF_LE_W(raw_entry->date));
 451         inode->i_ctime =
 452                 MSDOS_SB(inode->i_sb)->options.isvfat
 453                 ? date_dos2unix(CF_LE_W(raw_entry->ctime),CF_LE_W(raw_entry->cdate))
 454                 : inode->i_mtime;
 455         brelse(bh);
 456 }
 457 
 458 
 459 void fat_write_inode(struct inode *inode)
     /* [previous][next][first][last][top][bottom][index][help] */
 460 {
 461         struct super_block *sb = inode->i_sb;
 462         struct buffer_head *bh;
 463         struct msdos_dir_entry *raw_entry;
 464 
 465         inode->i_dirt = 0;
 466         if (inode->i_ino == MSDOS_ROOT_INO || !inode->i_nlink) return;
 467         if (!(bh = bread(inode->i_dev,inode->i_ino >> MSDOS_DPB_BITS,
 468             SECTOR_SIZE))) {
 469                 printk("dev = %s, ino = %ld\n",
 470                        kdevname(inode->i_dev), inode->i_ino);
 471                 panic("msdos_write_inode: unable to read i-node block");
 472         }
 473         raw_entry = &((struct msdos_dir_entry *) (bh->b_data))
 474             [inode->i_ino & (MSDOS_DPB-1)];
 475         if (S_ISDIR(inode->i_mode)) {
 476                 raw_entry->attr = ATTR_DIR;
 477                 raw_entry->size = 0;
 478         }
 479         else {
 480                 raw_entry->attr = ATTR_NONE;
 481                 raw_entry->size = CT_LE_L(inode->i_size);
 482         }
 483         raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) |
 484             MSDOS_I(inode)->i_attrs;
 485         raw_entry->start = CT_LE_L(MSDOS_I(inode)->i_start);
 486         fat_date_unix2dos(inode->i_mtime,&raw_entry->time,&raw_entry->date);
 487         raw_entry->time = CT_LE_W(raw_entry->time);
 488         raw_entry->date = CT_LE_W(raw_entry->date);
 489         if (MSDOS_SB(sb)->options.isvfat) {
 490                 fat_date_unix2dos(inode->i_ctime,&raw_entry->ctime,&raw_entry->cdate);
 491                 raw_entry->ctime = CT_LE_W(raw_entry->ctime);
 492                 raw_entry->cdate = CT_LE_W(raw_entry->cdate);
 493         }
 494         mark_buffer_dirty(bh, 1);
 495         brelse(bh);
 496 }
 497 
 498 
 499 int fat_notify_change(struct inode * inode,struct iattr * attr)
     /* [previous][next][first][last][top][bottom][index][help] */
 500 {
 501         int error;
 502 
 503         error = inode_change_ok(inode, attr);
 504         if (error)
 505                 return MSDOS_SB(inode->i_sb)->options.quiet ? 0 : error;
 506 
 507         if (((attr->ia_valid & ATTR_UID) && 
 508              (attr->ia_uid != MSDOS_SB(inode->i_sb)->options.fs_uid)) ||
 509             ((attr->ia_valid & ATTR_GID) && 
 510              (attr->ia_gid != MSDOS_SB(inode->i_sb)->options.fs_gid)) ||
 511             ((attr->ia_valid & ATTR_MODE) &&
 512              (attr->ia_mode & ~MSDOS_VALID_MODE)))
 513                 error = -EPERM;
 514 
 515         if (error)
 516                 return MSDOS_SB(inode->i_sb)->options.quiet ? 0 : error;
 517 
 518         inode_setattr(inode, attr);
 519 
 520         if (IS_NOEXEC(inode) && !S_ISDIR(inode->i_mode))
 521                 inode->i_mode &= S_IFMT | S_IRUGO | S_IWUGO;
 522         else
 523                 inode->i_mode |= S_IXUGO;
 524 
 525         inode->i_mode = ((inode->i_mode & S_IFMT) | ((((inode->i_mode & S_IRWXU
 526             & ~MSDOS_SB(inode->i_sb)->options.fs_umask) | S_IRUSR) >> 6)*S_IXUGO)) &
 527             ~MSDOS_SB(inode->i_sb)->options.fs_umask;
 528         return 0;
 529 }
 530 
 531 
 532 #ifdef MODULE
 533 int init_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 534 {
 535         return init_fat_fs();
 536 }
 537 
 538 
 539 void cleanup_module(void)
     /* [previous][next][first][last][top][bottom][index][help] */
 540 {
 541         /* Nothing to be done, really! */
 542         return;
 543 }
 544 #endif
 545 

/* [previous][next][first][last][top][bottom][index][help] */