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 + -
显示快捷键?