misc.c
来自「基于组件方式开发操作系统的OSKIT源代码」· C语言 代码 · 共 623 行 · 第 1/2 页
C
623 行
(((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_smap(dir,offset >> SECTOR_BITS)) == -1) return -1; 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; } break; } *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 + =
减小字号Ctrl + -
显示快捷键?