--- /src/linux/fs/msdos/dir.c Mon Jan 23 03:38:29 1995 +++ /src/1.2.9/fs/msdos/dir.c Mon May 15 10:14:22 1905 @@ -2,6 +2,7 @@ * linux/fs/msdos/dir.c * * Written 1992,1993 by Werner Almesberger + * Hacked 1995 by Albert Cahalan: albert@ccs.neu.edu or adc@coe.neu.edu * * MS-DOS directory handling functions */ @@ -92,7 +93,7 @@ bh = NULL; while ((ino = msdos_get_entry(inode,&filp->f_pos,&bh,&de)) > -1) { if (!IS_FREE(de->name) && !(de->attr & ATTR_VOLUME)) { - char bufname[13]; + char bufname[14]; /* dotfile support needs 14 */ char *ptname = bufname; for (i = last = 0; i < 8; i++) { if (!(c = de->name[i])) break; @@ -107,16 +108,20 @@ for (i2 = 0; i2 < 3; i2++) { if (!(c = de->ext[i2])) break; if (c >= 'A' && c <= 'Z') c += 32; - if (c != ' ') - last = i+1; + if (c != ' ') last = i+1; ptname[i] = c; - i++; + i++; } - if ((i = last) != 0) { + if((i=last) != 0) { if (!strcmp(de->name,MSDOS_DOT)) ino = inode->i_ino; else if (!strcmp(de->name,MSDOS_DOTDOT)) - ino = msdos_parent_ino(inode,0); + ino = msdos_parent_ino(inode,0); + if((de->attr & ATTR_HIDDEN) && (MSDOS_SB(sb)->dotsOK)){ + memmove(bufname+1,bufname,12); + i++; + ptname[0] = '.'; + } bufname[i] = '\0'; put_fs_long(ino,&dirent->d_ino); memcpy_tofs(dirent->d_name,bufname,i+1); @@ -124,7 +129,7 @@ PRINTK (("readdir avant brelse\n")); brelse(bh); PRINTK (("readdir retourne %d\n",i)); - return ROUND_UP(NAME_OFFSET(dirent) + i + 1); + return ROUND_UP(NAME_OFFSET(dirent) + i+1); } } } --- /src/linux/fs/msdos/inode.c Sun Feb 26 11:52:02 1995 +++ /src/1.2.9/fs/msdos/inode.c Mon May 15 10:14:22 1905 @@ -2,6 +2,7 @@ * linux/fs/msdos/inode.c * * Written 1992,1993 by Werner Almesberger + * Hacked 1995 by Albert Cahalan: albert@ccs.neu.edu or adc@coe.neu.edu */ #ifdef MODULE @@ -83,7 +84,7 @@ static int parse_options(char *options,char *check,char *conversion,uid_t *uid, gid_t *gid,int *umask,int *debug,int *fat,int *quiet, - int *blksize) + int *blksize, unsigned char *dotsOK) { char *this_char,*value; @@ -93,6 +94,7 @@ *gid = current->gid; *umask = current->fs->umask; *debug = *fat = *quiet = 0; + *dotsOK = 0; if (!options) return 1; for (this_char = strtok(options,","); this_char; this_char = strtok(NULL,",")) { if ((value = strchr(this_char,'=')) != NULL) @@ -157,6 +159,10 @@ printk ("MSDOS FS: Invalid blocksize (512 or 1024)\n"); } } + else if (!strcmp(this_char,"dots")) { + if (value) return 0; + *dotsOK = 1; + } else return 0; } return 1; @@ -172,6 +178,7 @@ struct msdos_boot_sector *b; int data_sectors,logical_sector_size,sector_mult; int debug,error,fat,quiet; + unsigned char dotsOK; char check,conversion; uid_t uid; gid_t gid; @@ -186,7 +193,7 @@ } } if (!parse_options((char *) data,&check,&conversion,&uid,&gid,&umask, - &debug,&fat,&quiet,&blksize) + &debug,&fat,&quiet,&blksize,&dotsOK) || (blksize != 512 && blksize != 1024)) { sb->s_dev = 0; MOD_DEC_USE_COUNT; @@ -295,6 +302,7 @@ MSDOS_SB(sb)->fs_gid = gid; MSDOS_SB(sb)->fs_umask = umask; MSDOS_SB(sb)->quiet = quiet; + MSDOS_SB(sb)->dotsOK = dotsOK; MSDOS_SB(sb)->free_clusters = -1; /* don't know yet */ MSDOS_SB(sb)->fat_wait = NULL; MSDOS_SB(sb)->fat_lock = 0; @@ -412,10 +420,10 @@ } } } - else { - inode->i_mode = MSDOS_MKMODE(raw_entry->attr,(IS_NOEXEC(inode) - ? S_IRUGO|S_IWUGO : S_IRWXUGO) & ~MSDOS_SB(inode->i_sb)->fs_umask) | - S_IFREG; + else { /* not a directory */ + inode->i_mode = MSDOS_MKMODE(raw_entry->attr, + (IS_NOEXEC(inode) ? S_IRUGO|S_IWUGO : S_IRWXUGO) + & ~MSDOS_SB(inode->i_sb)->fs_umask) | S_IFREG; inode->i_op = sb->s_blocksize == 1024 ? &msdos_file_inode_operations_1024 : &msdos_file_inode_operations; @@ -451,12 +459,13 @@ } raw_entry = &((struct msdos_dir_entry *) (bh->b_data)) [inode->i_ino & (MSDOS_DPB-1)]; +/* TODO: put if..else into MSDOS_MKATTR or use lookup */ if (S_ISDIR(inode->i_mode)) { - raw_entry->attr = ATTR_DIR; + raw_entry->attr = ATTR_DIR; /* TODO */ raw_entry->size = 0; } else { - raw_entry->attr = ATTR_NONE; + raw_entry->attr = ATTR_NONE; /* TODO */ raw_entry->size = CT_LE_L(inode->i_size); } raw_entry->attr |= MSDOS_MKATTR(inode->i_mode) | @@ -475,8 +484,7 @@ int error; error = inode_change_ok(inode, attr); - if (error) - return error; + if (error) return error; if (((attr->ia_valid & ATTR_UID) && (attr->ia_uid != MSDOS_SB(inode->i_sb)->fs_uid)) || @@ -501,13 +509,12 @@ ~MSDOS_SB(inode->i_sb)->fs_umask; return 0; } + #ifdef MODULE char kernel_version[] = UTS_RELEASE; - -static struct file_system_type msdos_fs_type = { - msdos_read_super, "msdos", 1, NULL -}; +static struct file_system_type msdos_fs_type + = { msdos_read_super, "msdos", 1, NULL }; int init_module(void) { --- /src/linux/fs/msdos/namei.c Mon Jan 23 03:38:29 1995 +++ /src/1.2.9/fs/msdos/namei.c Mon May 15 11:35:12 1905 @@ -2,6 +2,7 @@ * linux/fs/msdos/namei.c * * Written 1992,1993 by Werner Almesberger + * Hacked 1995 by Albert Cahalan: albert@ccs.neu.edu or adc@coe.neu.edu */ #ifdef MODULE @@ -22,24 +23,23 @@ #define PRINTK(x) /* MS-DOS "device special files" */ - static char *reserved_names[] = { "CON ","PRN ","NUL ","AUX ", "LPT1 ","LPT2 ","LPT3 ","LPT4 ", "COM1 ","COM2 ","COM3 ","COM4 ", NULL }; - /* Characters that are undesirable in an MS-DOS file name */ - static char bad_chars[] = "*?<>|\""; static char bad_if_strict[] = "+=,; "; -/* Formats an MS-DOS file name. Rejects invalid names. */ - -static int msdos_format_name(char conv,const char *name,int len,char *res, - int dot_dirs) +/***** Formats an MS-DOS file name. Rejects invalid names. */ +static int msdos_format_name(char conv, const char *name, int len, + char *res, int dot_dirs, unsigned char dotsOK) + /* conv=strict/relaxed name=proposed_name */ + /* len=name_length res=msdos_name? */ + /* dot_dirs=? dotsOK=use_hidden_attrib */ { char *walk,**reserved; unsigned char c; @@ -52,7 +52,12 @@ while (len--) *res++ = '.'; return 0; } - space = 1; /* disallow names starting with a dot */ + if (name[0] == '.'){ + if(!dotsOK) return -EINVAL; + name++; len--; + /* .filename and filename are same, only one lists */ + } + space = 1; /* disallow names that _really_ start with a dot */ c = 0; for (walk = res; len && walk-res < 8; walk++) { c = *name++; @@ -62,8 +67,8 @@ if (c >= 'A' && c <= 'Z' && conv == 's') return -EINVAL; if (c < ' ' || c == ':' || c == '\\') return -EINVAL; if (c == '.') break; - space = c == ' '; - *walk = c >= 'a' && c <= 'z' ? c-32 : c; + space = (c == ' '); + *walk = (c >= 'a' && c <= 'z') ? c-32 : c; /* uppercase */ } if (space) return -EINVAL; if (conv == 's' && len && c != '.') { @@ -96,20 +101,31 @@ } -/* Locates a directory entry. */ - +/***** Locates a directory entry. Uses unformatted name. */ static int msdos_find(struct inode *dir,const char *name,int len, struct buffer_head **bh,struct msdos_dir_entry **de,int *ino) { char msdos_name[MSDOS_NAME]; - int res; + int res,dotsOK; + char scantype; - if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len, - msdos_name,1)) < 0) return res; - return msdos_scan(dir,msdos_name,bh,de,ino); + dotsOK = MSDOS_SB(dir->i_sb)->dotsOK; + if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check, + name,len,msdos_name,1,dotsOK)) < 0) return res; + if((name[0]=='.') && dotsOK){ + switch(len){ + case 0: panic("Empty name in msdos_find!"); + case 1: scantype = SCAN_ANY; break; + case 2: scantype = ((name[1]=='.')?SCAN_ANY:SCAN_HID); break; + default: scantype = SCAN_HID; + } + } else { + scantype = (dotsOK ? SCAN_NOTHID : SCAN_ANY); + } + return msdos_scan(dir,msdos_name,bh,de,ino,scantype); } - +/***** get inode using directory and name */ int msdos_lookup(struct inode *dir,const char *name,int len, struct inode **result) { @@ -119,15 +135,12 @@ struct buffer_head *bh; struct inode *next; - PRINTK (("msdos_lookup\n")); - *result = NULL; if (!dir) return -ENOENT; if (!S_ISDIR(dir->i_mode)) { iput(dir); return -ENOENT; } - PRINTK (("msdos_lookup 2\n")); if (len == 1 && name[0] == '.') { *result = dir; return 0; @@ -139,26 +152,20 @@ if (!(*result = iget(dir->i_sb,ino))) return -EACCES; return 0; } - PRINTK (("msdos_lookup 3\n")); if ((res = msdos_find(dir,name,len,&bh,&de,&ino)) < 0) { iput(dir); return res; } - PRINTK (("msdos_lookup 4\n")); if (bh) brelse(bh); - PRINTK (("msdos_lookup 4.5\n")); -/* printk("lookup: ino=%d\n",ino); */ if (!(*result = iget(dir->i_sb,ino))) { iput(dir); return -EACCES; } - PRINTK (("msdos_lookup 5\n")); if (MSDOS_I(*result)->i_busy) { /* mkdir in progress */ iput(*result); iput(dir); return -ENOENT; } - PRINTK (("msdos_lookup 6\n")); while (MSDOS_I(*result)->i_old) { next = MSDOS_I(*result)->i_old; iput(*result); @@ -168,28 +175,25 @@ return -ENOENT; } } - PRINTK (("msdos_lookup 7\n")); iput(dir); - PRINTK (("msdos_lookup 8\n")); return 0; } -/* Creates a directory entry (name is already formatted). */ - -static int msdos_create_entry(struct inode *dir,char *name,int is_dir, - struct inode **result) +/***** Creates a directory entry (name is already formatted). */ +static int msdos_create_entry(struct inode *dir,char *name, + int is_dir, int is_hid, struct inode **result) { struct super_block *sb = dir->i_sb; struct buffer_head *bh; struct msdos_dir_entry *de; int res,ino; - if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) { + if ((res = msdos_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) { if (res != -ENOENT) return res; if (dir->i_ino == MSDOS_ROOT_INO) return -ENOSPC; if ((res = msdos_add_cluster(dir)) < 0) return res; - if ((res = msdos_scan(dir,NULL,&bh,&de,&ino)) < 0) return res; + if ((res = msdos_scan(dir,NULL,&bh,&de,&ino,SCAN_ANY)) < 0) return res; } /* * XXX all times should be set by caller upon successful completion. @@ -199,6 +203,7 @@ memcpy(de->name,name,MSDOS_NAME); memset(de->unused, 0, sizeof(de->unused)); de->attr = is_dir ? ATTR_DIR : ATTR_ARCH; + de->attr = is_hid ? (de->attr|ATTR_HIDDEN) : (de->attr&~ATTR_HIDDEN); de->start = 0; date_unix2dos(dir->i_mtime,&de->time,&de->date); de->size = 0; @@ -213,7 +218,7 @@ return 0; } - +/***** Create a file or directory */ int msdos_create(struct inode *dir,const char *name,int len,int mode, struct inode **result) { @@ -221,22 +226,23 @@ struct buffer_head *bh; struct msdos_dir_entry *de; char msdos_name[MSDOS_NAME]; - int ino,res; + int ino,res,is_hid; if (!dir) return -ENOENT; if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len, - msdos_name,0)) < 0) { + msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) { iput(dir); return res; } + is_hid = (name[0]=='.') && (msdos_name[0]!='.'); lock_creation(); - if (msdos_scan(dir,msdos_name,&bh,&de,&ino) >= 0) { + if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY) >= 0) { unlock_creation(); brelse(bh); iput(dir); return -EEXIST; } - res = msdos_create_entry(dir,msdos_name,S_ISDIR(mode),result); + res = msdos_create_entry(dir,msdos_name,S_ISDIR(mode),is_hid,result); unlock_creation(); iput(dir); return res; @@ -244,7 +250,6 @@ #ifdef DEBUG - static void dump_fat(struct super_block *sb,int start) { printk("["); @@ -259,10 +264,10 @@ } printk("]\n"); } - #endif +/***** Make a directory */ int msdos_mkdir(struct inode *dir,const char *name,int len,int mode) { struct super_block *sb = dir->i_sb; @@ -270,21 +275,22 @@ struct msdos_dir_entry *de; struct inode *inode,*dot; char msdos_name[MSDOS_NAME]; - int ino,res; + int ino,res,is_hid; if ((res = msdos_format_name(MSDOS_SB(dir->i_sb)->name_check,name,len, - msdos_name,0)) < 0) { + msdos_name,0,MSDOS_SB(dir->i_sb)->dotsOK)) < 0) { iput(dir); return res; } + is_hid = (name[0]=='.') && (msdos_name[0]!='.'); lock_creation(); - if (msdos_scan(dir,msdos_name,&bh,&de,&ino) >= 0) { + if (msdos_scan(dir,msdos_name,&bh,&de,&ino,SCAN_ANY) >= 0) { unlock_creation(); brelse(bh); iput(dir); return -EEXIST; } - if ((res = msdos_create_entry(dir,msdos_name,1,&inode)) < 0) { + if ((res = msdos_create_entry(dir,msdos_name,1,is_hid,&inode)) < 0) { unlock_creation(); iput(dir); return res; @@ -293,14 +299,14 @@ inode->i_nlink = 2; /* no need to mark them dirty */ MSDOS_I(inode)->i_busy = 1; /* prevent lookups */ if ((res = msdos_add_cluster(inode)) < 0) goto mkdir_error; - if ((res = msdos_create_entry(inode,MSDOS_DOT,1,&dot)) < 0) + if ((res = msdos_create_entry(inode,MSDOS_DOT,1,0,&dot)) < 0) goto mkdir_error; dot->i_size = inode->i_size; /* doesn't grow in the 2nd create_entry */ MSDOS_I(dot)->i_start = MSDOS_I(inode)->i_start; dot->i_nlink = inode->i_nlink; dot->i_dirt = 1; iput(dot); - if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,&dot)) < 0) + if ((res = msdos_create_entry(inode,MSDOS_DOTDOT,1,0,&dot)) < 0) goto mkdir_error; unlock_creation(); dot->i_size = dir->i_size; @@ -321,6 +327,7 @@ } +/***** see if directory is empty */ static int msdos_empty(struct inode *dir) { struct super_block *sb = dir->i_sb; @@ -346,7 +353,7 @@ return 0; } - +/***** Remove a directory */ int msdos_rmdir(struct inode *dir,const char *name,int len) { struct super_block *sb = dir->i_sb; @@ -368,8 +375,7 @@ res = -EBUSY; if (dir->i_dev != inode->i_dev || dir == inode) goto rmdir_done; res = msdos_empty(inode); - if (res) - goto rmdir_done; + if (res) goto rmdir_done; inode->i_nlink = 0; inode->i_ctime = dir->i_ctime = dir->i_mtime = CURRENT_TIME; dir->i_nlink--; @@ -385,6 +391,7 @@ } +/***** Unlink a file */ static int msdos_unlinkx( struct inode *dir, const char *name, @@ -422,21 +429,19 @@ return res; } -int msdos_unlink(struct inode *dir,const char *name,int len) -{ +/***** unlink, as called for msdosfs */ +int msdos_unlink(struct inode *dir,const char *name,int len){ return msdos_unlinkx (dir,name,len,1); } -/* - Special entry for umsdos -*/ -int msdos_unlink_umsdos(struct inode *dir,const char *name,int len) -{ +/***** Special unlink for umsdos */ +int msdos_unlink_umsdos(struct inode *dir,const char *name,int len){ return msdos_unlinkx (dir,name,len,0); } +/***** rename within a directory */ static int rename_same_dir(struct inode *old_dir,char *old_name, struct inode *new_dir,char *new_name,struct buffer_head *old_bh, - struct msdos_dir_entry *old_de,int old_ino) + struct msdos_dir_entry *old_de,int old_ino,int is_hid) { struct super_block *sb = old_dir->i_sb; struct buffer_head *new_bh; @@ -444,8 +449,8 @@ struct inode *new_inode,*old_inode; int new_ino,exists,error; - if (!strncmp(old_name,new_name,MSDOS_NAME)) return 0; - exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0; + if (!strncmp(old_name,new_name,MSDOS_NAME)) goto set_hid; + exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0; if (*(unsigned char *) old_de->name == DELETED_FLAG) { if (exists) brelse(new_bh); return -ENOENT; @@ -455,9 +460,9 @@ brelse(new_bh); return -EIO; } - error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ? - msdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR) - ? -EPERM : 0; + error = S_ISDIR(new_inode->i_mode) + ? (old_de->attr & ATTR_DIR) ? msdos_empty(new_inode) : -EPERM + : (old_de->attr & ATTR_DIR) ? -EPERM : 0; if (error) { iput(new_inode); brelse(new_bh); @@ -476,19 +481,27 @@ brelse(new_bh); } memcpy(old_de->name,new_name,MSDOS_NAME); +set_hid: + old_de->attr = is_hid + ? (old_de->attr | ATTR_HIDDEN) + : (old_de->attr &~ ATTR_HIDDEN); mark_buffer_dirty(old_bh, 1); - if (MSDOS_SB(old_dir->i_sb)->conversion == 'a') /* update binary info */ - if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) { - msdos_read_inode(old_inode); - iput(old_inode); - } + /* update binary info for conversion, i_attrs */ + if ((old_inode = iget(old_dir->i_sb,old_ino)) != NULL) { + msdos_read_inode(old_inode); + MSDOS_I(old_inode)->i_attrs = is_hid + ? (MSDOS_I(old_inode)->i_attrs | ATTR_HIDDEN) + : (MSDOS_I(old_inode)->i_attrs &~ ATTR_HIDDEN); + iput(old_inode); + } return 0; } +/***** rename across directories */ static int rename_diff_dir(struct inode *old_dir,char *old_name, struct inode *new_dir,char *new_name,struct buffer_head *old_bh, - struct msdos_dir_entry *old_de,int old_ino) + struct msdos_dir_entry *old_de,int old_ino,int is_hid) { struct super_block *sb = old_dir->i_sb; struct buffer_head *new_bh,*free_bh,*dotdot_bh; @@ -508,13 +521,12 @@ if (!(walk = iget(new_dir->i_sb,ino))) return -EIO; } iput(walk); - while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino)) < - 0) { + while ((error = msdos_scan(new_dir,NULL,&free_bh,&free_de,&free_ino,SCAN_ANY))<0) { if (error != -ENOENT) return error; error = msdos_add_cluster(new_dir); if (error) return error; } - exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino) >= 0; + exists = msdos_scan(new_dir,new_name,&new_bh,&new_de,&new_ino,SCAN_ANY) >= 0; if (!(old_inode = iget(old_dir->i_sb,old_ino))) { brelse(free_bh); if (exists) brelse(new_bh); @@ -533,9 +545,9 @@ brelse(new_bh); return -EIO; } - error = S_ISDIR(new_inode->i_mode) ? (old_de->attr & ATTR_DIR) ? - msdos_empty(new_inode) : -EPERM : (old_de->attr & ATTR_DIR) - ? -EPERM : 0; + error = S_ISDIR(new_inode->i_mode) + ? (old_de->attr & ATTR_DIR) ? msdos_empty(new_inode) : -EPERM + : (old_de->attr & ATTR_DIR) ? -EPERM : 0; if (error) { iput(new_inode); iput(old_inode); @@ -550,6 +562,7 @@ } memcpy(free_de,old_de,sizeof(struct msdos_dir_entry)); memcpy(free_de->name,new_name,MSDOS_NAME); + free_de->attr = is_hid ? (free_de->attr|ATTR_HIDDEN) : (free_de->attr&~ATTR_HIDDEN); if (!(free_inode = iget(new_dir->i_sb,free_ino))) { free_de->name[0] = DELETED_FLAG; /* Don't mark free_bh as dirty. Both states are supposed to be equivalent. */ @@ -581,7 +594,7 @@ } if (S_ISDIR(old_inode->i_mode)) { if ((error = msdos_scan(old_inode,MSDOS_DOTDOT,&dotdot_bh, - &dotdot_de,&dotdot_ino)) < 0) goto rename_done; + &dotdot_de,&dotdot_ino,SCAN_ANY)) < 0) goto rename_done; if (!(dotdot_inode = iget(old_inode->i_sb,dotdot_ino))) { brelse(dotdot_bh); error = -EIO; @@ -605,7 +618,7 @@ return error; } - +/***** Rename, a wrapper for rename_same_dir & rename_diff_dir */ int msdos_rename(struct inode *old_dir,const char *old_name,int old_len, struct inode *new_dir,const char *new_name,int new_len) { @@ -613,20 +626,21 @@ char old_msdos_name[MSDOS_NAME],new_msdos_name[MSDOS_NAME]; struct buffer_head *old_bh; struct msdos_dir_entry *old_de; - int old_ino,error; + int old_ino,error,is_hid; if ((error = msdos_format_name(MSDOS_SB(old_dir->i_sb)->name_check, - old_name,old_len,old_msdos_name,1)) < 0) goto rename_done; + old_name,old_len,old_msdos_name,1,MSDOS_SB(old_dir->i_sb)->dotsOK)) < 0) goto rename_done; if ((error = msdos_format_name(MSDOS_SB(new_dir->i_sb)->name_check, - new_name,new_len,new_msdos_name,0)) < 0) goto rename_done; + new_name,new_len,new_msdos_name,0,MSDOS_SB(new_dir->i_sb)->dotsOK)) < 0) goto rename_done; + is_hid = (new_name[0]=='.') && (new_msdos_name[0]!='.'); if ((error = msdos_scan(old_dir,old_msdos_name,&old_bh,&old_de, - &old_ino)) < 0) goto rename_done; + &old_ino,is_hid?SCAN_HID:SCAN_NOTHID)) < 0) goto rename_done; lock_creation(); if (old_dir == new_dir) error = rename_same_dir(old_dir,old_msdos_name,new_dir, - new_msdos_name,old_bh,old_de,old_ino); + new_msdos_name,old_bh,old_de,old_ino,is_hid); else error = rename_diff_dir(old_dir,old_msdos_name,new_dir, - new_msdos_name,old_bh,old_de,old_ino); + new_msdos_name,old_bh,old_de,old_ino,is_hid); unlock_creation(); brelse(old_bh); rename_done: --- /src/linux/fs/msdos/misc.c Wed Mar 22 03:31:42 1995 +++ /src/1.2.9/fs/msdos/misc.c Mon May 15 10:14:22 1905 @@ -226,16 +226,13 @@ /* Linear day numbers of the respective 1sts in non-leap years. */ - static int day_n[] = { 0,31,59,90,120,151,181,212,243,273,304,334,0,0,0,0 }; /* JanFebMarApr May Jun Jul Aug Sep Oct Nov Dec */ - extern struct timezone sys_tz; /* Convert a MS-DOS time/date pair to a UNIX date (seconds since 1 1 70). */ - int date_dos2unix(unsigned short time,unsigned short date) { int month,year,secs; @@ -252,9 +249,7 @@ /* Convert linear UNIX date to a MS-DOS time/date pair. */ - -void date_unix2dos(int unix_date,unsigned short *time, - unsigned short *date) +void date_unix2dos(int unix_date, unsigned short *time, unsigned short *date) { int day,year,nl_day,month; @@ -340,7 +335,7 @@ #define RSS_NAME /* search for name */ \ done = !strncmp(data[entry].name,name,MSDOS_NAME) && \ - !(data[entry].attr & ATTR_VOLUME); + !(data[entry].attr & ATTR_VOLUME); #define RSS_START /* search for start cluster */ \ done = !IS_FREE(data[entry].name) && CF_LE_W(data[entry].start) == *number; @@ -367,7 +362,7 @@ static int raw_scan_sector(struct super_block *sb,int sector,char *name, int *number,int *ino,struct buffer_head **res_bh, - struct msdos_dir_entry **res_de) + struct msdos_dir_entry **res_de,char scantype) { struct buffer_head *bh; struct msdos_dir_entry *data; @@ -377,8 +372,17 @@ if (!(bh = bread(sb->s_dev,sector,SECTOR_SIZE))) return -EIO; data = (struct msdos_dir_entry *) bh->b_data; for (entry = 0; entry < MSDOS_DPS; entry++) { - if (name) RSS_NAME - else { + +/* RSS_COUNT: if (data[entry].name == name) done=true else done=false. */ + + if (name) { + RSS_NAME + if (done && scantype) { /* scantype != SCAN_ANY */ + done = (data[entry].attr & ATTR_HIDDEN) + ? (scantype==SCAN_HID) + : (scantype==SCAN_NOTHID); + } + } else { if (!ino) RSS_COUNT else { if (number) RSS_START @@ -407,13 +411,13 @@ */ static int raw_scan_root(struct super_block *sb,char *name,int *number,int *ino, - struct buffer_head **res_bh,struct msdos_dir_entry **res_de) + struct buffer_head **res_bh,struct msdos_dir_entry **res_de,char scantype) { int count,cluster; for (count = 0; count < MSDOS_SB(sb)->dir_entries/MSDOS_DPS; count++) { - if ((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count, - name,number,ino,res_bh,res_de)) >= 0) return cluster; + if((cluster = raw_scan_sector(sb,MSDOS_SB(sb)->dir_start+count, + name,number,ino,res_bh,res_de,scantype)) >= 0) return cluster; } return -ENOENT; } @@ -426,7 +430,7 @@ static int raw_scan_nonroot(struct super_block *sb,int start,char *name, int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry - **res_de) + **res_de,char scantype) { int count,cluster; @@ -437,7 +441,7 @@ for (count = 0; count < MSDOS_SB(sb)->cluster_size; count++) { if ((cluster = raw_scan_sector(sb,(start-2)* MSDOS_SB(sb)->cluster_size+MSDOS_SB(sb)->data_start+ - count,name,number,ino,res_bh,res_de)) >= 0) + count,name,number,ino,res_bh,res_de,scantype)) >= 0) return cluster; } if (!(start = fat_access(sb,start,-1))) { @@ -460,12 +464,14 @@ * being created. */ -static int raw_scan(struct super_block *sb,int start,char *name,int *number, - int *ino,struct buffer_head **res_bh,struct msdos_dir_entry **res_de) +static int raw_scan(struct super_block *sb, int start, char *name, + int *number, int *ino, struct buffer_head **res_bh, + struct msdos_dir_entry **res_de, char scantype) { - if (start) - return raw_scan_nonroot(sb,start,name,number,ino,res_bh,res_de); - else return raw_scan_root(sb,name,number,ino,res_bh,res_de); + if (start) return raw_scan_nonroot + (sb,start,name,number,ino,res_bh,res_de,scantype); + else return raw_scan_root /* TODO explain why only 7 parameters */ + (sb,name,number,ino,res_bh,res_de,scantype); } @@ -484,19 +490,19 @@ if (dir->i_ino == MSDOS_ROOT_INO) return dir->i_ino; if (!locked) lock_creation(); /* prevent renames */ if ((current = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,MSDOS_DOTDOT, - &zero,NULL,NULL,NULL)) < 0) { + &zero,NULL,NULL,NULL,SCAN_ANY)) < 0) { if (!locked) unlock_creation(); return current; } if (!current) nr = MSDOS_ROOT_INO; else { if ((prev = raw_scan(dir->i_sb,current,MSDOS_DOTDOT,&zero,NULL, - NULL,NULL)) < 0) { + NULL,NULL,SCAN_ANY)) < 0) { if (!locked) unlock_creation(); return prev; } if ((error = raw_scan(dir->i_sb,prev,NULL,¤t,&nr,NULL, - NULL)) < 0) { + NULL,SCAN_ANY)) < 0) { if (!locked) unlock_creation(); return error; } @@ -507,8 +513,8 @@ /* - * msdos_subdirs counts the number of sub-directories of dir. It can be run - * on directories being created. + * msdos_subdirs counts the number of sub-directories of dir. + * It can be run on directories being created. */ int msdos_subdirs(struct inode *dir) @@ -517,11 +523,11 @@ count = 0; if (dir->i_ino == MSDOS_ROOT_INO) - (void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL); + (void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL,SCAN_ANY); else { if (!MSDOS_I(dir)->i_start) return 0; /* in mkdir */ else (void) raw_scan_nonroot(dir->i_sb,MSDOS_I(dir)->i_start, - NULL,&count,NULL,NULL,NULL); + NULL,&count,NULL,NULL,NULL,SCAN_ANY); } return count; } @@ -533,14 +539,14 @@ */ int msdos_scan(struct inode *dir,char *name,struct buffer_head **res_bh, - struct msdos_dir_entry **res_de,int *ino) + struct msdos_dir_entry **res_de,int *ino, char scantype) { int res; - if (name) - res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,name,NULL,ino, - res_bh,res_de); - else res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,NULL,NULL,ino, - res_bh,res_de); - return res < 0 ? res : 0; + res = (name) + ? raw_scan(dir->i_sb, MSDOS_I(dir)->i_start, + name, NULL, ino, res_bh, res_de, scantype) + : raw_scan(dir->i_sb, MSDOS_I(dir)->i_start, + NULL, NULL, ino, res_bh, res_de, scantype); + return res<0 ? res : 0; } --- /src/linux/include/linux/msdos_fs.h Sun Feb 26 11:52:02 1995 +++ /src/1.2.9/include/linux/msdos_fs.h Mon May 15 10:14:22 1905 @@ -3,6 +3,7 @@ /* * The MS-DOS filesystem constants/structures + * Hacked 1995 by Albert Cahalan: albert@ccs.neu.edu or adc@coe.neu.edu */ #include #include @@ -32,6 +33,11 @@ #define ATTR_UNUSED (ATTR_VOLUME | ATTR_ARCH | ATTR_SYS | ATTR_HIDDEN) /* attribute bits that are copied "as is" */ +#define SCAN_ANY 0 /* either hidden or not */ +#define SCAN_HID 1 /* only hidden */ +#define SCAN_NOTHID 2 /* only not hidden */ +#define SCAN_NOTANY 3 /* test name, then use SCAN_HID or SCAN_NOTHID */ + #define DELETED_FLAG 0xe5 /* marks file as deleted when in name[0] */ #define IS_FREE(n) (!*(n) || *(unsigned char *) (n) == DELETED_FLAG || \ *(unsigned char *) (n) == FD_FILL_BYTE) @@ -96,16 +102,13 @@ }; /* Determine whether this FS has kB-aligned data. */ - #define MSDOS_CAN_BMAP(mib) (!(((mib)->cluster_size & 1) || \ ((mib)->data_start & 1))) /* Convert attribute bits and a mask to the UNIX mode. */ - #define MSDOS_MKMODE(a,m) (m & (a & ATTR_RO ? S_IRUGO|S_IXUGO : S_IRWXUGO)) /* Convert the UNIX mode to MS-DOS attribute bits. */ - #define MSDOS_MKATTR(m) ((m & S_IWUGO) ? ATTR_NONE : ATTR_RO) #ifdef __KERNEL__ @@ -124,7 +127,7 @@ extern int msdos_get_entry(struct inode *dir,loff_t *pos,struct buffer_head **bh, struct msdos_dir_entry **de); extern int msdos_scan(struct inode *dir,char *name,struct buffer_head **res_bh, - struct msdos_dir_entry **res_de,int *ino); + struct msdos_dir_entry **res_de,int *ino,char scantype); extern int msdos_parent_ino(struct inode *dir,int locked); extern int msdos_subdirs(struct inode *dir); --- /src/linux/include/linux/msdos_fs_sb.h Wed Dec 1 07:44:15 1993 +++ /src/1.2.9/include/linux/msdos_fs_sb.h Mon May 15 10:14:22 1905 @@ -3,6 +3,7 @@ /* * MS-DOS file system in-core superblock data + * Hacked 1995 by Albert Cahalan: albert@ccs.neu.edu or adc@coe.neu.edu */ struct msdos_sb_info { @@ -22,6 +23,7 @@ int fat_lock; int prev_free; /* previously returned free cluster number */ int free_clusters; /* -1 if undefined */ + unsigned char dotsOK; /* allow dotfiles via hidden attribute */ }; #endif