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

📄 namei.c

📁 elinux jffs初始版本 具体了解JFFS的文件系统!
💻 C
📖 第 1 页 / 共 3 页
字号:
}static loff_t vfat_find_free_slots(struct inode *dir,int slots){	struct super_block *sb = dir->i_sb;	loff_t offset, curr;	struct msdos_dir_entry *de;	struct buffer_head *bh;	struct inode *inode;	int ino;	int row;	int done;	int res;	int added;	PRINTK(("vfat_find_free_slots: find %d free slots\n", slots));	offset = curr = 0;	bh = NULL;	row = 0;	ino = fat_get_entry(dir,&curr,&bh,&de);	for (added = 0; added < 2; added++) {		while (ino > -1) {			done = IS_FREE(de->name);			if (done) {				inode = iget(sb,ino);				if (inode) {					/* Directory slots of busy deleted files aren't available yet. */					done = !MSDOS_I(inode)->i_busy;					/* PRINTK(("inode %d still busy\n", ino)); */				}				iput(inode);			}			if (done) {				row++;				if (row == slots) {					fat_brelse(sb, bh);					/* printk("----- Free offset at %d\n", offset); */					return offset;				}			} else {				row = 0;				offset = curr;			}			ino = fat_get_entry(dir,&curr,&bh,&de);		}		if ((dir->i_ino == MSDOS_ROOT_INO) &&		    (MSDOS_SB(sb)->fat_bits != 32)) 			return -ENOSPC;		if ((res = fat_add_cluster(dir)) < 0) return res;		ino = fat_get_entry(dir,&curr,&bh,&de);	}	return -ENOSPC;}/* Translate a string, including coded sequences into Unicode */static intxlate_to_uni(const char *name, int len, char *outname, int *outlen,	     int escape, int utf8, struct nls_table *nls){	int i;	const unsigned char *ip;	char *op;	int fill;	unsigned char c1, c2, c3;	if (utf8) {		*outlen = utf8_mbstowcs((__u16 *) outname, name, PAGE_SIZE);		if (name[len-1] == '.')			*outlen-=2;		op = &outname[*outlen * sizeof(__u16)];	} else {		if (name[len-1] == '.') 			len--;		op = outname;		if (nls) {			/* XXX: i is incorrectly computed. */			for (i = 0, ip = name, op = outname, *outlen = 0;			     i < len && *outlen <= 260; i++, *outlen += 1)			{				if (escape && (*ip == ':')) {					if (i > len - 4) return -EINVAL;					c1 = fat_esc2uni[ip[1]];					c2 = fat_esc2uni[ip[2]];					c3 = fat_esc2uni[ip[3]];					if (c1 == 255 || c2 == 255 || c3 == 255)						return -EINVAL;					*op++ = (c1 << 4) + (c2 >> 2);					*op++ = ((c2 & 0x3) << 6) + c3;					ip += 4;				} else {					*op++ = nls->charset2uni[*ip].uni1;					*op++ = nls->charset2uni[*ip].uni2;					ip++;				}			}		} else {			for (i = 0, ip = name, op = outname, *outlen = 0;			     i < len && *outlen <= 260; i++, *outlen += 1)			{				*op++ = *ip++;				*op++ = 0;			}		}	}	if (*outlen > 260)		return -ENAMETOOLONG;	if (*outlen % 13) {		*op++ = 0;		*op++ = 0;		*outlen += 1;		if (*outlen % 13) {			fill = 13 - (*outlen % 13);			for (i = 0; i < fill; i++) {				*op++ = 0xff;				*op++ = 0xff;			}			*outlen += fill;		}	}	return 0;}static intvfat_fill_long_slots(struct msdos_dir_slot *ds, const char *name, int len,		     char *msdos_name, int *slots,		     int uni_xlate, int utf8, struct nls_table *nls){	struct msdos_dir_slot *ps;	struct msdos_dir_entry *de;	int res;	int slot;	unsigned char cksum;	char *uniname;	const char *ip;	unsigned long page;	int unilen;	int i;	loff_t offset;	if (name[len-1] == '.') len--;	if(!(page = __get_free_page(GFP_KERNEL)))		return -ENOMEM;	uniname = (char *) page;	res = xlate_to_uni(name, len, uniname, &unilen, uni_xlate, utf8, nls);	if (res < 0) {		free_page(page);		return res;	}	*slots = unilen / 13;	for (cksum = i = 0; i < 11; i++) {		cksum = (((cksum&1)<<7)|((cksum&0xfe)>>1)) + msdos_name[i];	}	PRINTK(("vfat_fill_long_slots 3: slots=%d\n",*slots));	for (ps = ds, slot = *slots; slot > 0; slot--, ps++) {		int end, j;		PRINTK(("vfat_fill_long_slots 4\n"));		ps->id = slot;		ps->attr = ATTR_EXT;		ps->reserved = 0;		ps->alias_checksum = cksum;		ps->start = 0;		PRINTK(("vfat_fill_long_slots 5: uniname=%s\n",uniname));		offset = (slot - 1) * 26;		ip = &uniname[offset];		j = offset;		end = 0;		for (i = 0; i < 10; i += 2) {			ps->name0_4[i] = *ip++;			ps->name0_4[i+1] = *ip++;		}		PRINTK(("vfat_fill_long_slots 6\n"));		for (i = 0; i < 12; i += 2) {			ps->name5_10[i] = *ip++;			ps->name5_10[i+1] = *ip++;		}		PRINTK(("vfat_fill_long_slots 7\n"));		for (i = 0; i < 4; i += 2) {			ps->name11_12[i] = *ip++;			ps->name11_12[i+1] = *ip++;		}	}	PRINTK(("vfat_fill_long_slots 8\n"));	ds[0].id |= 0x40;	de = (struct msdos_dir_entry *) ps;	PRINTK(("vfat_fill_long_slots 9\n"));	strncpy(de->name, msdos_name, MSDOS_NAME);	free_page(page);	return 0;}		static int vfat_build_slots(struct inode *dir,const char *name,int len,     struct msdos_dir_slot *ds, int *slots, int *is_long){	struct msdos_dir_entry *de;	char msdos_name[MSDOS_NAME];	int res, xlate, utf8;	struct nls_table *nls;	PRINTK(("Entering vfat_build_slots: name=%s, len=%d\n", name, len));	de = (struct msdos_dir_entry *) ds;	xlate = MSDOS_SB(dir->i_sb)->options.unicode_xlate;	utf8 = MSDOS_SB(dir->i_sb)->options.utf8;	nls = MSDOS_SB(dir->i_sb)->nls_io;	*slots = 1;	*is_long = 0;	if (len == 1 && name[0] == '.') {		strncpy(de->name, MSDOS_DOT, MSDOS_NAME);	} else if (len == 2 && name[0] == '.' && name[1] == '.') {		strncpy(de->name, MSDOS_DOT, MSDOS_NAME);	} else {		PRINTK(("vfat_build_slots 4\n"));		res = vfat_valid_shortname(name, len, 1, utf8);		if (res > -1) {			PRINTK(("vfat_build_slots 5a\n"));			res = vfat_format_name(name, len, de->name, 1, utf8);			PRINTK(("vfat_build_slots 5b\n"));		} else {			res = vfat_create_shortname(dir, name, len, msdos_name, utf8);			if (res < 0) {				return res;			}			res = vfat_valid_longname(name, len, 1, xlate);			if (res < 0) {				return res;			}			*is_long = 1;			return vfat_fill_long_slots(ds, name, len, msdos_name,						    slots, xlate, utf8, nls);		}	}	return 0;}static int vfat_readdir_cb(	filldir_t filldir,	void * buf,	const char * name,	int name_len,	int is_long,	off_t offset,	off_t short_offset,	int long_slots,	ino_t ino){	struct vfat_find_info *vf = (struct vfat_find_info *) buf;	const char *s1, *s2;	int i;#ifdef DEBUG	if (debug) printk("cb: vf.name=%s, len=%d, name=%s, name_len=%d\n",			  vf->name, vf->len, name, name_len);#endif	/* Filenames cannot end in '.' or we treat like it has none */	if (vf->len != name_len) {		if ((vf->len != name_len + 1) || (vf->name[name_len] != '.')) {			return 0;		}	}	s1 = name; s2 = vf->name;	for (i = 0; i < name_len; i++) {		if (vf->new_filename && !vf->posix) {			if (tolower(*s1) != tolower(*s2))				return 0;		} else {			if (*s1 != *s2)				return 0;		}		s1++; s2++;	}	vf->found = 1;	vf->is_long = is_long;	vf->offset = (offset == 2) ? 0 : offset;	vf->short_offset = (short_offset == 2) ? 0 : short_offset;	vf->long_slots = long_slots;	vf->ino = ino;	return -1;}static int vfat_find(struct inode *dir,const char *name,int len,    int find_long, int new_filename,int is_dir,struct slot_info *sinfo_out){	struct super_block *sb = dir->i_sb;	struct vfat_find_info vf;	struct file fil;	struct buffer_head *bh;	struct msdos_dir_entry *de;	struct msdos_dir_slot *ps;	loff_t offset;	struct msdos_dir_slot *ds;	int is_long;	int slots, slot;	int res;	PRINTK(("Entering vfat_find\n"));	ds = (struct msdos_dir_slot *)	    kmalloc(sizeof(struct msdos_dir_slot)*MSDOS_SLOTS, GFP_KERNEL);	if (ds == NULL) return -ENOMEM;	fil.f_pos = 0;	vf.name = name;	vf.len = len;	vf.new_filename = new_filename;	vf.found = 0;	vf.posix = MSDOS_SB(sb)->options.posixfs;	res = fat_readdirx(dir,&fil,(void *)&vf,vfat_readdir_cb,NULL,1,find_long,0);	PRINTK(("vfat_find: Debug 1\n"));	if (res < 0) goto cleanup;	if (vf.found) {		if (new_filename) {			res = -EEXIST;			goto cleanup;		}		sinfo_out->longname_offset = vf.offset;		sinfo_out->shortname_offset = vf.short_offset;		sinfo_out->is_long = vf.is_long;		sinfo_out->long_slots = vf.long_slots;		sinfo_out->total_slots = vf.long_slots + 1;		sinfo_out->ino = vf.ino;		PRINTK(("vfat_find: Debug 2\n"));		res = 0;		goto cleanup;	}	PRINTK(("vfat_find: Debug 3\n"));	if (!vf.found && !new_filename) {		res = -ENOENT;		goto cleanup;	}		res = vfat_build_slots(dir, name, len, ds, &slots, &is_long);	if (res < 0) goto cleanup;	de = (struct msdos_dir_entry *) ds;	bh = NULL;	if (new_filename) {		PRINTK(("vfat_find: create file 1\n"));		if (is_long) slots++;		offset = vfat_find_free_slots(dir, slots);		if (offset < 0) {			res = offset;			goto cleanup;		}		PRINTK(("vfat_find: create file 2\n"));		/* Now create the new entry */		bh = NULL;		for (slot = 0, ps = ds; slot < slots; slot++, ps++) {			PRINTK(("vfat_find: create file 3, slot=%d\n",slot));			sinfo_out->ino = fat_get_entry(dir,&offset,&bh,&de);			if (sinfo_out->ino < 0) {				PRINTK(("vfat_find: problem\n"));				res = sinfo_out->ino;				goto cleanup;			}			memcpy(de, ps, sizeof(struct msdos_dir_slot));			fat_mark_buffer_dirty(sb, bh, 1);		}		PRINTK(("vfat_find: create file 4\n"));		dir->i_ctime = dir->i_mtime = dir->i_atime = CURRENT_TIME;		dir->i_dirt = 1;		PRINTK(("vfat_find: create file 5\n"));		fat_date_unix2dos(dir->i_mtime,&de->time,&de->date);		de->ctime_ms = 0;		de->ctime = de->time;		de->adate = de->cdate = de->date;		de->start = 0;		de->starthi = 0;		de->size = 0;		de->attr = is_dir ? ATTR_DIR : ATTR_ARCH;		de->lcase = CASE_LOWER_BASE | CASE_LOWER_EXT;		fat_mark_buffer_dirty(sb, bh, 1);		fat_brelse(sb, bh);		sinfo_out->is_long = (slots > 1) ? 1 : 0;		if (sinfo_out->is_long) {			sinfo_out->long_slots = slots - 1;		} else {			sinfo_out->long_slots = 0;		}		sinfo_out->total_slots = slots;		sinfo_out->shortname_offset = offset - sizeof(struct msdos_dir_slot);		sinfo_out->longname_offset = offset - sizeof(struct msdos_dir_slot) * slots;		res = 0;		return 0;	} else {		res = -ENOENT;	}cleanup:	kfree(ds);	return res;}int vfat_lookup(struct inode *dir,const char *name,int len,    struct inode **result){	int res, ino;	struct inode *next;	struct slot_info sinfo;		PRINTK (("vfat_lookup: name=%s, len=%d\n", name, len));	*result = NULL;	if (!dir) return -ENOENT;	if (!S_ISDIR(dir->i_mode)) {		iput(dir);		return -ENOENT;	}	PRINTK (("vfat_lookup 2\n"));	if (len == 1 && name[0] == '.') {		*result = dir;		return 0;	}	if (len == 2 && name[0] == '.' && name[1] == '.') {		ino = fat_parent_ino(dir,0);		iput(dir);		if (ino < 0) return ino;		if (!(*result = iget(dir->i_sb,ino))) return -EACCES;		return 0;	}	if (dcache_lookup(dir, name, len, (unsigned long *) &ino) && ino) {		iput(dir);		if (!(*result = iget(dir->i_sb, ino)))			return -EACCES;		return 0;	}	PRINTK (("vfat_lookup 3\n"));	if ((res = vfat_find(dir,name,len,1,0,0,&sinfo)) < 0) {		iput(dir);		return res;	}	PRINTK (("vfat_lookup 4.5\n"));	if (!(*result = iget(dir->i_sb,sinfo.ino))) {		iput(dir);		return -EACCES;	}	PRINTK (("vfat_lookup 5\n"));	if (!(*result)->i_sb ||	    ((*result)->i_sb->s_magic != MSDOS_SUPER_MAGIC)) {		/* crossed a mount point into a non-msdos fs */		iput(dir);		return 0;	}	if (MSDOS_I(*result)->i_busy) { /* mkdir in progress */		iput(*result);		iput(dir);		return -ENOENT;	}	PRINTK (("vfat_lookup 6\n"));	while (MSDOS_I(*result)->i_old) {		next = MSDOS_I(*result)->i_old;		iput(*result);		if (!(*result = iget(next->i_sb,next->i_ino))) {			fat_fs_panic(dir->i_sb,"vfat_lookup: Can't happen");			iput(dir);			return -ENOENT;		}	}	iput(dir);	return 0;}static int vfat_create_entry(struct inode *dir,const char *name,int len,    int is_dir, struct inode **result){	struct super_block *sb = dir->i_sb;	int res,ino;	loff_t offset;	struct buffer_head *bh;	struct msdos_dir_entry *de;	struct slot_info sinfo;	PRINTK(("vfat_create_entry 1\n"));	res = vfat_find(dir, name, len, 1, 1, is_dir, &sinfo);	if (res < 0) {		return res;	}	offset = sinfo.shortname_offset;	PRINTK(("vfat_create_entry 2\n"));	bh = NULL;	ino = fat_get_entry(dir, &offset, &bh, &de);	if (ino < 0) {		PRINTK(("vfat_mkdir problem\n"));		if (bh)			fat_brelse(sb, bh);		return ino;	}	PRINTK(("vfat_create_entry 3\n"));	if ((*result = iget(dir->i_sb,ino)) != NULL)		vfat_read_inode(*result);	fat_brelse(sb, bh);	if (!*result)		return -EIO;	(*result)->i_mtime = (*result)->i_atime = (*result)->i_ctime =	    CURRENT_TIME;	(*result)->i_dirt = 1;	(*result)->i_version = ++event;	dir->i_version = event;	dcache_add(dir, name, len, ino);	return 0;}int vfat_create(struct inode *dir,const char *name,int len,int mode,	struct inode **result){	int res;	if (!dir) return -ENOENT;	fat_lock_creation();	res = vfat_create_entry(dir,name,len,0,result);	if (res < 0) PRINTK(("vfat_create: unable to get new entry\n"));	fat_unlock_creation();	iput(dir);	return res;}static int vfat_create_a_dotdir(struct inode *dir,struct inode *parent,     struct buffer_head *bh,     struct msdos_dir_entry *de,int ino,const char *name, int isdot){	struct super_block *sb = dir->i_sb;	struct inode *dot;	PRINTK(("vfat_create_a_dotdir 1\n"));	/*	 * XXX all times should be set by caller upon successful completion.	 */	dir->i_atime = dir->i_ctime = dir->i_mtime = CURRENT_TIME;	dir->i_dirt = 1;	memcpy(de->name,name,MSDOS_NAME);	de->lcase = 0;	de->attr = ATTR_DIR;

⌨️ 快捷键说明

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