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

📄 dir.c

📁 嵌入式系统设计与实例开发实验教材二源码 多线程应用程序设计 串行端口程序设计 AD接口实验 CAN总线通信实验 GPS通信实验 Linux内核移植与编译实验 IC卡读写实验 SD驱动使
💻 C
📖 第 1 页 / 共 2 页
字号:
			goto RecEnd;		if (de->attr != ATTR_EXT && (de->attr & ATTR_VOLUME))			goto RecEnd;		if (de->attr != ATTR_EXT && IS_FREE(de->name))			goto RecEnd;	} else {		if ((de->attr & ATTR_VOLUME) || IS_FREE(de->name))			goto RecEnd;	}	if (isvfat && de->attr == ATTR_EXT) {		struct msdos_dir_slot *ds;		unsigned char id;		unsigned char slot;		unsigned char slots;		unsigned char sum;		unsigned char alias_checksum;		if (!unicode) {			unicode = (wchar_t *)				__get_free_page(GFP_KERNEL);			if (!unicode) {				filp->f_pos = cpos;				fat_brelse(sb, bh);				return -ENOMEM;			}		}ParseLong:		slots = 0;		ds = (struct msdos_dir_slot *) de;		id = ds->id;		if (!(id & 0x40))			goto RecEnd;		slots = id & ~0x40;		if (slots > 20 || !slots)	/* ceil(256 * 2 / 26) */			goto RecEnd;		long_slots = slots;		alias_checksum = ds->alias_checksum;		slot = slots;		while (1) {			int offset;			slot--;			offset = slot * 13;			fat16_towchar(unicode + offset, ds->name0_4, 5);			fat16_towchar(unicode + offset + 5, ds->name5_10, 6);			fat16_towchar(unicode + offset + 11, ds->name11_12, 2);			if (ds->id & 0x40) {				unicode[offset + 13] = 0;			}			if (fat_get_entry(inode,&cpos,&bh,&de,&ino) == -1)				goto EODir;			if (slot == 0)				break;			ds = (struct msdos_dir_slot *) de;			if (ds->attr !=  ATTR_EXT)				goto RecEnd;	/* XXX */			if ((ds->id & ~0x40) != slot)				goto ParseLong;			if (ds->alias_checksum != alias_checksum)				goto ParseLong;		}		if (de->name[0] == (__s8) DELETED_FLAG)			goto RecEnd;		if (de->attr ==  ATTR_EXT)			goto ParseLong;		if (IS_FREE(de->name) || (de->attr & ATTR_VOLUME))			goto RecEnd;		for (sum = 0, i = 0; i < 11; i++)			sum = (((sum&1)<<7)|((sum&0xfe)>>1)) + de->name[i];		if (sum != alias_checksum)			long_slots = 0;	}	if ((de->attr & ATTR_HIDDEN) && MSDOS_SB(sb)->options.dotsOK) {		*ptname++ = '.';		dotoffset = 1;	}	for (i = 0; i < 8; i++) {		/* see namei.c, msdos_format_name */		if (de->name[i] == 0x05)			work[i] = 0xE5;		else			work[i] = de->name[i];	}	for (i = 0, j = 0, last = 0, last_u = 0; i < 8;) {		if (!(c = work[i])) break;		chl = fat_shortname2uni(nls_disk, &work[i], 8 - i,					&bufuname[j++], opt_shortname,					de->lcase & CASE_LOWER_BASE);		if (chl <= 1) {			ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c;			if (c != ' ') {				last = i;				last_u = j;			}		} else {			last_u = j;			for (chi = 0; chi < chl && i < 8; chi++) {				ptname[i] = work[i];				i++; last = i;			}		}	}	i = last;	j = last_u;	fat_short2uni(nls_disk, ".", 1, &bufuname[j++]);	ptname[i++] = '.';	for (i2 = 0; i2 < 3;) {		if (!(c = de->ext[i2])) break;		chl = fat_shortname2uni(nls_disk, &de->ext[i2], 3 - i2,					&bufuname[j++], opt_shortname,					de->lcase & CASE_LOWER_EXT);		if (chl <= 1) {			i2++;			ptname[i++] = (!nocase && c>='A' && c<='Z') ? c+32 : c;			if (c != ' ') {				last = i;				last_u = j;			}		} else {			last_u = j;			for (chi = 0; chi < chl && i2 < 3; chi++) {				ptname[i++] = de->ext[i2++];				last = i;			}		}	}	if (!last)		goto RecEnd;	i = last + dotoffset;	j = last_u;	lpos = cpos - (long_slots+1)*sizeof(struct msdos_dir_entry);	if (!memcmp(de->name,MSDOS_DOT,11))		inum = inode->i_ino;	else if (!memcmp(de->name,MSDOS_DOTDOT,11)) {/*		inum = fat_parent_ino(inode,0); */		inum = filp->f_dentry->d_parent->d_inode->i_ino;	} else {		struct inode *tmp = fat_iget(sb, ino);		if (tmp) {			inum = tmp->i_ino;			iput(tmp);		} else			inum = iunique(sb, MSDOS_ROOT_INO);	}	if (isvfat) {		bufuname[j] = 0x0000;		i = utf8 ? utf8_wcstombs(bufname, bufuname, sizeof(bufname))			 : uni16_to_x8(bufname, bufuname, uni_xlate, nls_io);	}	if (!long_slots||shortnames) {		if (both)			bufname[i] = '\0';		if (filldir(dirent, bufname, i, *furrfu, inum,			    (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)			goto FillFailed;	} else {		char longname[275];		int long_len = utf8			? utf8_wcstombs(longname, unicode, sizeof(longname))			: uni16_to_x8(longname, unicode, uni_xlate,				      nls_io);		if (both) {			memcpy(&longname[long_len+1], bufname, i);			long_len += i;		}		if (filldir(dirent, longname, long_len, *furrfu, inum,			    (de->attr & ATTR_DIR) ? DT_DIR : DT_REG) < 0)			goto FillFailed;	}RecEnd:	furrfu = &lpos;	filp->f_pos = cpos;	goto GetNew;EODir:	filp->f_pos = cpos;FillFailed:	if (bh)		fat_brelse(sb, bh);	if (unicode) {		free_page((unsigned long) unicode);	}	return 0;}int fat_readdir(struct file *filp, void *dirent, filldir_t filldir){	struct inode *inode = filp->f_dentry->d_inode;	return fat_readdirx(inode, filp, dirent, filldir, 0, 0);}static int vfat_ioctl_fill(	void * buf,	const char * name,	int name_len,	loff_t offset,	ino_t ino,	unsigned int d_type){	struct dirent *d1 = (struct dirent *)buf;	struct dirent *d2 = d1 + 1;	int len, slen;	int dotdir;	get_user(len, &d1->d_reclen);	if (len != 0) {		return -1;	}	if ((name_len == 1 && name[0] == '.') ||	    (name_len == 2 && name[0] == '.' && name[1] == '.')) {		dotdir = 1;		len = name_len;	} else {		dotdir = 0;		len = strlen(name);	}	if (len != name_len) {		copy_to_user(d2->d_name, name, len);		put_user(0, d2->d_name + len);		put_user(len, &d2->d_reclen);		put_user(ino, &d2->d_ino);		put_user(offset, &d2->d_off);		slen = name_len - len;		copy_to_user(d1->d_name, name+len+1, slen);		put_user(0, d1->d_name+slen);		put_user(slen, &d1->d_reclen);	} else {		put_user(0, d2->d_name);		put_user(0, &d2->d_reclen);		copy_to_user(d1->d_name, name, len);		put_user(0, d1->d_name+len);		put_user(len, &d1->d_reclen);	}	PRINTK(("FAT d1=%p d2=%p len=%d, name_len=%d\n",		d1, d2, len, name_len));	return 0;}int fat_dir_ioctl(struct inode * inode, struct file * filp,		  unsigned int cmd, unsigned long arg){	int err;	/*	 * We want to provide an interface for Samba to be able	 * to get the short filename for a given long filename.	 * Samba should use this ioctl instead of readdir() to	 * get the information it needs.	 */	switch (cmd) {	case VFAT_IOCTL_READDIR_BOTH: {		struct dirent *d1 = (struct dirent *)arg;		err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2]));		if (err)			return err;		put_user(0, &d1->d_reclen);		return fat_readdirx(inode,filp,(void *)arg,				    vfat_ioctl_fill, 0, 1);	}	case VFAT_IOCTL_READDIR_SHORT: {		struct dirent *d1 = (struct dirent *)arg;		put_user(0, &d1->d_reclen);		err = verify_area(VERIFY_WRITE, d1, sizeof(struct dirent[2]));		if (err)			return err;		return fat_readdirx(inode,filp,(void *)arg,				    vfat_ioctl_fill, 1, 1);	}	default:		/* forward ioctl to CVF extension */	       if (MSDOS_SB(inode->i_sb)->cvf_format &&		   MSDOS_SB(inode->i_sb)->cvf_format->cvf_dir_ioctl)		       return MSDOS_SB(inode->i_sb)->cvf_format			       ->cvf_dir_ioctl(inode,filp,cmd,arg);		return -EINVAL;	}	return 0;}/***** See if directory is empty */int fat_dir_empty(struct inode *dir){	loff_t pos;	struct buffer_head *bh;	struct msdos_dir_entry *de;	int ino,result = 0;	pos = 0;	bh = NULL;	while (fat_get_entry(dir,&pos,&bh,&de,&ino) > -1) {		/* Ignore vfat longname entries */		if (de->attr == ATTR_EXT)			continue;		if (!IS_FREE(de->name) && 		    strncmp(de->name,MSDOS_DOT   , MSDOS_NAME) &&		    strncmp(de->name,MSDOS_DOTDOT, MSDOS_NAME)) {			result = -ENOTEMPTY;			break;		}	}	if (bh)		fat_brelse(dir->i_sb, bh);	return result;}/* This assumes that size of cluster is above the 32*slots */int fat_add_entries(struct inode *dir,int slots, struct buffer_head **bh,		  struct msdos_dir_entry **de, int *ino){	struct super_block *sb = dir->i_sb;	loff_t offset, curr;	int row;	struct buffer_head *new_bh;	offset = curr = 0;	*bh = NULL;	row = 0;	while (fat_get_entry(dir,&curr,bh,de,ino) > -1) {		if (IS_FREE((*de)->name)) {			if (++row == slots)				return offset;		} else {			row = 0;			offset = curr;		}	}	if ((dir->i_ino == MSDOS_ROOT_INO) && (MSDOS_SB(sb)->fat_bits != 32)) 		return -ENOSPC;	new_bh = fat_extend_dir(dir);	if (!new_bh)		return -ENOSPC;	fat_brelse(sb, new_bh);	do fat_get_entry(dir,&curr,bh,de,ino); while (++row<slots);	return offset;}int fat_new_dir(struct inode *dir, struct inode *parent, int is_vfat){	struct super_block *sb = dir->i_sb;	struct buffer_head *bh;	struct msdos_dir_entry *de;	__u16 date, time;	if ((bh = fat_extend_dir(dir)) == NULL) return -ENOSPC;	/* zeroed out, so... */	fat_date_unix2dos(dir->i_mtime,&time,&date);	de = (struct msdos_dir_entry*)&bh->b_data[0];	memcpy(de[0].name,MSDOS_DOT,MSDOS_NAME);	memcpy(de[1].name,MSDOS_DOTDOT,MSDOS_NAME);	de[0].attr = de[1].attr = ATTR_DIR;	de[0].time = de[1].time = CT_LE_W(time);	de[0].date = de[1].date = CT_LE_W(date);	if (is_vfat) {	/* extra timestamps */		de[0].ctime = de[1].ctime = CT_LE_W(time);		de[0].adate = de[0].cdate =			de[1].adate = de[1].cdate = CT_LE_W(date);	}	de[0].start = CT_LE_W(MSDOS_I(dir)->i_logstart);	de[0].starthi = CT_LE_W(MSDOS_I(dir)->i_logstart>>16);	de[1].start = CT_LE_W(MSDOS_I(parent)->i_logstart);	de[1].starthi = CT_LE_W(MSDOS_I(parent)->i_logstart>>16);	fat_mark_buffer_dirty(sb, bh);	fat_brelse(sb, bh);	dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;	mark_inode_dirty(dir);	return 0;}/* * Overrides for Emacs so that we follow Linus's tabbing style. * Emacs will notice this stuff at the end of the file and automatically * adjust the settings for this buffer only.  This must remain at the end * of the file. * --------------------------------------------------------------------------- * Local variables: * c-indent-level: 8 * c-brace-imaginary-offset: 0 * c-brace-offset: -8 * c-argdecl-indent: 8 * c-label-offset: -8 * c-continued-statement-offset: 8 * c-continued-brace-offset: 0 * End: */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -