⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 misc.c

📁 Linux内核源代码 为压缩文件 是<<Linux内核>>一书中的源代码
💻 C
📖 第 1 页 / 共 2 页
字号:
	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 + -