📄 misc.c
字号:
secs = (time & 31)*2+60*((time >> 5) & 63)+(time >> 11)*3600+86400* ((date & 31)-1+day_n[month]+(year/4)+year*365-((year & 3) == 0 && month < 2 ? 1 : 0)+3653); /* days since 1.1.70 plus 80's leap day */ secs += sys_tz.tz_minuteswest*60; return secs;}/* Convert linear UNIX date to a MS-DOS time/date pair. */void fat_date_unix2dos(int unix_date,unsigned short *time, unsigned short *date){ int day,year,nl_day,month; unix_date -= sys_tz.tz_minuteswest*60; if (sys_tz.tz_dsttime) unix_date += 3600; *time = (unix_date % 60)/2+(((unix_date/60) % 60) << 5)+ (((unix_date/3600) % 24) << 11); day = unix_date/86400-3652; year = day/365; if ((year+3)/4+365*year > day) year--; day -= (year+3)/4+365*year; if (day == 59 && !(year & 3)) { nl_day = day; month = 2; } else { nl_day = (year & 3) || day <= 59 ? day : day-1; for (month = 0; month < 12; month++) if (day_n[month] > nl_day) break; } *date = nl_day-day_n[month-1]+1+(month << 5)+(year << 9);}/* Returns the inode number of the directory entry at offset pos. If bh is non-NULL, it is brelse'd before. Pos is incremented. The buffer header is returned in bh. AV. Most often we do it item-by-item. Makes sense to optimize. AV. OK, there we go: if both bh and de are non-NULL we assume that we just AV. want the next entry (took one explicit de=NULL in vfat/namei.c). AV. It's done in fat_get_entry() (inlined), here the slow case lives. AV. Additionally, when we return -1 (i.e. reached the end of directory) AV. we make bh NULL. */int fat__get_entry(struct inode *dir, loff_t *pos,struct buffer_head **bh, struct msdos_dir_entry **de, int *ino){ struct super_block *sb = dir->i_sb; int sector, offset; while (1) { offset = *pos; PRINTK (("get_entry offset %d\n",offset)); if (*bh) fat_brelse(sb, *bh); *bh = NULL; if ((sector = fat_bmap(dir,offset >> SECTOR_BITS)) == -1) return -1; PRINTK (("get_entry sector %d %p\n",sector,*bh)); PRINTK (("get_entry sector apres brelse\n")); if (!sector) return -1; /* beyond EOF */ *pos += sizeof(struct msdos_dir_entry); if (!(*bh = fat_bread(sb, sector))) { printk("Directory sread (sector 0x%x) failed\n",sector); continue; } PRINTK (("get_entry apres sread\n")); *de = (struct msdos_dir_entry *) ((*bh)->b_data+(offset & (SECTOR_SIZE-1))); *ino = (sector << MSDOS_DPS_BITS)+((offset & (SECTOR_SIZE-1)) >> MSDOS_DIR_BITS); return 0; }}/* * Now an ugly part: this set of directory scan routines works on clusters * rather than on inodes and sectors. They are necessary to locate the '..' * directory "inode". raw_scan_sector operates in four modes: * * name number ino action * -------- -------- -------- ------------------------------------------------- * non-NULL - X Find an entry with that name * NULL non-NULL non-NULL Find an entry whose data starts at *number * NULL non-NULL NULL Count subdirectories in *number. (*) * NULL NULL non-NULL Find an empty entry * * (*) The return code should be ignored. It DOES NOT indicate success or * failure. *number has to be initialized to zero. * * - = not used, X = a value is returned unless NULL * * If res_bh is non-NULL, the buffer is not deallocated but returned to the * caller on success. res_de is set accordingly. * * If cont is non-zero, raw_found continues with the entry after the one * res_bh/res_de point to. */#define RSS_NAME /* search for name */ \ done = !strncmp(data[entry].name,name,MSDOS_NAME) && \ !(data[entry].attr & ATTR_VOLUME);#define RSS_START /* search for start cluster */ \ done = !IS_FREE(data[entry].name) \ && ( \ ( \ (MSDOS_SB(sb)->fat_bits != 32) ? 0 : (CF_LE_W(data[entry].starthi) << 16) \ ) \ | CF_LE_W(data[entry].start) \ ) == *number;#define RSS_FREE /* search for free entry */ \ { \ done = IS_FREE(data[entry].name); \ }#define RSS_COUNT /* count subdirectories */ \ { \ done = 0; \ if (!IS_FREE(data[entry].name) && (data[entry].attr & ATTR_DIR)) \ (*number)++; \ }static int raw_scan_sector(struct super_block *sb,int sector,const char *name, int *number,int *ino,struct buffer_head **res_bh, struct msdos_dir_entry **res_de){ struct buffer_head *bh; struct msdos_dir_entry *data; int entry,start,done; if (!(bh = fat_bread(sb,sector))) return -EIO; data = (struct msdos_dir_entry *) bh->b_data; for (entry = 0; entry < MSDOS_DPS; entry++) {/* RSS_COUNT: if (data[entry].name == name) done=true else done=false. */ if (name) { RSS_NAME } else { if (!ino) RSS_COUNT else { if (number) RSS_START else RSS_FREE } } if (done) { if (ino) *ino = sector*MSDOS_DPS+entry; start = CF_LE_W(data[entry].start); if (MSDOS_SB(sb)->fat_bits == 32) { start |= (CF_LE_W(data[entry].starthi) << 16); } if (!res_bh) fat_brelse(sb, bh); else { *res_bh = bh; *res_de = &data[entry]; } return start; } } fat_brelse(sb, bh); return -ENOENT;}/* * raw_scan_root performs raw_scan_sector on the root directory until the * requested entry is found or the end of the directory is reached. */static int raw_scan_root(struct super_block *sb,const char *name,int *number,int *ino, struct buffer_head **res_bh,struct msdos_dir_entry **res_de){ 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; } return -ENOENT;}/* * raw_scan_nonroot performs raw_scan_sector on a non-root directory until the * requested entry is found or the end of the directory is reached. */static int raw_scan_nonroot(struct super_block *sb,int start,const char *name, int *number,int *ino,struct buffer_head **res_bh,struct msdos_dir_entry **res_de){ int count,cluster;#ifdef DEBUG printk("raw_scan_nonroot: start=%d\n",start);#endif do { 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) return cluster; } if (!(start = fat_access(sb,start,-1))) { fat_fs_panic(sb,"FAT error"); break; }#ifdef DEBUG printk("next start: %d\n",start);#endif } while (start != -1); return -ENOENT;}/* * raw_scan performs raw_scan_sector on any sector. * * NOTE: raw_scan must not be used on a directory that is is the process of * being created. */static int raw_scan(struct super_block *sb, int start, const char *name, int *number, int *ino, struct buffer_head **res_bh, struct msdos_dir_entry **res_de){ 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);}/* * fat_parent_ino returns the inode number of the parent directory of dir. * File creation has to be deferred while fat_parent_ino is running to * prevent renames. * * AV. Bad, bad, bad... We need a mapping that would give us inode by * first cluster. Sheeeeit... OK, we can do it on fat_fill_inode() and * update on fat_add_cluster(). When will we remove it? fat_clear_inode() * and fat_truncate() to zero? */int fat_parent_ino(struct inode *dir,int locked){ static int zero = 0; int error,curr,prev,nr; PRINTK(("fat_parent_ino: Debug 0\n")); if (!S_ISDIR(dir->i_mode)) panic("Non-directory fed to m_p_i"); if (dir->i_ino == MSDOS_ROOT_INO) return dir->i_ino; if (!locked) fat_lock_creation(); /* prevent renames */ if ((curr = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start,MSDOS_DOTDOT, &zero,NULL,NULL,NULL)) < 0) { if (!locked) fat_unlock_creation(); return curr; } PRINTK(("fat_parent_ino: Debug 1 curr=%d\n", curr)); if (!curr) nr = MSDOS_ROOT_INO; else { PRINTK(("fat_parent_ino: Debug 2\n")); if ((prev = raw_scan(dir->i_sb,curr,MSDOS_DOTDOT,&zero,NULL, NULL,NULL)) < 0) { PRINTK(("fat_parent_ino: Debug 3 prev=%d\n", prev)); if (!locked) fat_unlock_creation(); return prev; } PRINTK(("fat_parent_ino: Debug 4 prev=%d\n", prev)); if (prev == 0 && MSDOS_SB(dir->i_sb)->fat_bits == 32) { prev = MSDOS_SB(dir->i_sb)->root_cluster; } if ((error = raw_scan(dir->i_sb,prev,NULL,&curr,&nr,NULL, NULL)) < 0) { PRINTK(("fat_parent_ino: Debug 5 error=%d\n", error)); if (!locked) fat_unlock_creation(); return error; } PRINTK(("fat_parent_ino: Debug 6 nr=%d\n", nr)); } if (!locked) fat_unlock_creation(); return nr;}/* * fat_subdirs counts the number of sub-directories of dir. It can be run * on directories being created. */int fat_subdirs(struct inode *dir){ int count; count = 0; if ((dir->i_ino == MSDOS_ROOT_INO) && (MSDOS_SB(dir->i_sb)->fat_bits != 32)) { (void) raw_scan_root(dir->i_sb,NULL,&count,NULL,NULL,NULL); } else { if ((dir->i_ino != MSDOS_ROOT_INO) && !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); } return count;}/* * Scans a directory for a given file (name points to its formatted name) or * for an empty directory slot (name is NULL). Returns an error code or zero. */int fat_scan(struct inode *dir,const char *name,struct buffer_head **res_bh, struct msdos_dir_entry **res_de,int *ino){ int res; res = raw_scan(dir->i_sb,MSDOS_I(dir)->i_start, name, NULL, ino, res_bh, res_de); return res<0 ? res : 0;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -