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

📄 file_hdr.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 2 页
字号:
/* * linux/fs/hfs/file_hdr.c * * Copyright (C) 1995-1997  Paul H. Hargrove * This file may be distributed under the terms of the GNU General Public License. * * This file contains the file_ops and inode_ops for the metadata * files under the AppleDouble and Netatalk representations. * * The source code distributions of Netatalk, versions 1.3.3b2 and * 1.4b2, were used as a specification of the location and format of * files used by Netatalk's afpd.  No code from Netatalk appears in * hfs_fs.  hfs_fs is not a work ``derived'' from Netatalk in the * sense of intellectual property law. * * "XXX" in a comment is a note to myself to consider changing something. * * In function preconditions the term "valid" applied to a pointer to * a structure means that the pointer is non-NULL and the structure it * points to has all fields initialized to consistent values. * * XXX: Note the reason that there is not bmap() for AppleDouble * header files is that dynamic nature of their structure make it * very difficult to safely mmap them.  Maybe in the distant future * I'll get bored enough to implement it. */#include "hfs.h"#include <linux/hfs_fs_sb.h>#include <linux/hfs_fs_i.h>#include <linux/hfs_fs.h>/* prodos types */#define PRODOSI_FTYPE_DIR   0x0F#define PRODOSI_FTYPE_TEXT  0x04#define PRODOSI_FTYPE_8BIT  0xFF#define PRODOSI_FTYPE_16BIT 0xB3#define PRODOSI_AUXTYPE_DIR 0x0200/*================ Forward declarations ================*/static loff_t      hdr_llseek(struct file *, loff_t, int);static hfs_rwret_t hdr_read(struct file *, char *, hfs_rwarg_t, loff_t *);static hfs_rwret_t hdr_write(struct file *, const char *,			     hfs_rwarg_t, loff_t *);/*================ Global variables ================*/struct file_operations hfs_hdr_operations = {	llseek:		hdr_llseek,	read:		hdr_read,	write:		hdr_write,	fsync:		file_fsync,};struct inode_operations hfs_hdr_inode_operations = {	setattr:	hfs_notify_change_hdr,};const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = {	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */	__constant_htonl(HFS_HDR_VERSION_2),	/* version */	6,					/* entries */	{					/* descr[] */		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4},		{HFS_HDR_RSRC,  HFS_DBL_HDR_LEN,                           ~0}	},	{					/* order[] */		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[0],		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[1],		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[2],		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[3],		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[4],		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[5]	}};const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout = {	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */	__constant_htonl(HFS_HDR_VERSION_2),	/* version */	5,					/* entries */	{					/* descr[] */		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4}	},	{					/* order[] */		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[0],		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[1],		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[2],		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[3],		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[4]	}};const struct hfs_hdr_layout hfs_nat2_hdr_layout = {	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */	__constant_htonl(HFS_HDR_VERSION_2),	/* version */	9,					/* entries */	{					/* descr[] */		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},		{HFS_HDR_AFPI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4},		{HFS_HDR_SNAME,  offsetof(struct hfs_dbl_hdr, short_name), ~0},		{HFS_HDR_PRODOSI,  offsetof(struct hfs_dbl_hdr, prodosi),   8},		{HFS_HDR_RSRC,  HFS_NAT_HDR_LEN,                           ~0}	},	{					/* order[] */		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[5],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[6],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[7],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[8]	}};const struct hfs_hdr_layout hfs_nat_hdr_layout = {	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */	__constant_htonl(HFS_HDR_VERSION_1),	/* version */	5,					/* entries */	{					/* descr[] */		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},		{HFS_HDR_OLDI,  offsetof(struct hfs_dbl_hdr, create_time), 16},		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},		{HFS_HDR_RSRC,  HFS_NAT_HDR_LEN,                           ~0},	},	{					/* order[] */		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4]	}};/*================ File-local variables ================*/static const char fstype[16] =	{'M','a','c','i','n','t','o','s','h',' ',' ',' ',' ',' ',' ',' '};/*================ File-local data types ================*/struct hdr_hdr {        hfs_lword_t	magic;        hfs_lword_t	version;        hfs_byte_t	filler[16];        hfs_word_t	entries;        hfs_byte_t	descrs[12*HFS_HDR_MAX];}  __attribute__((packed));/*================ File-local functions ================*//* * dlength() */static int dlength(const struct hfs_hdr_descr *descr,		   const struct hfs_cat_entry *entry){	hfs_u32 length = descr->length;	/* handle auto-sized entries */	if (length == ~0) {		switch (descr->id) {		case HFS_HDR_DATA:			if (entry->type == HFS_CDR_FIL) {				length = entry->u.file.data_fork.lsize;			} else {				length = 0;			}			break;		case HFS_HDR_RSRC:			if (entry->type == HFS_CDR_FIL) {				length = entry->u.file.rsrc_fork.lsize;			} else {				length = 0;			}			break;		case HFS_HDR_FNAME:			length = entry->key.CName.Len;			break;		case HFS_HDR_SNAME:		default:			length = 0;		}	}	return length;}/* * hdr_build_meta() */static void hdr_build_meta(struct hdr_hdr *meta,			   const struct hfs_hdr_layout *layout,			   const struct hfs_cat_entry *entry){	const struct hfs_hdr_descr *descr;	hfs_byte_t *ptr;	int lcv;	hfs_put_nl(layout->magic,   meta->magic);	hfs_put_nl(layout->version, meta->version);	if (layout->version == htonl(HFS_HDR_VERSION_1)) {		memcpy(meta->filler, fstype, 16);	} else {		memset(meta->filler, 0, 16);	}	hfs_put_hs(layout->entries, meta->entries);	memset(meta->descrs, 0, sizeof(meta->descrs));	for (lcv = 0, descr = layout->descr, ptr = meta->descrs;	     lcv < layout->entries; ++lcv, ++descr, ptr += 12) {		hfs_put_hl(descr->id,             ptr);		hfs_put_hl(descr->offset,         ptr + 4);		hfs_put_hl(dlength(descr, entry), ptr + 8);	}}/* * dup_layout () */static struct hfs_hdr_layout *dup_layout(const struct hfs_hdr_layout *old){	struct hfs_hdr_layout *new;	int lcv;	if (HFS_NEW(new)) {		memcpy(new, old, sizeof(*new));		for (lcv = 0; lcv < new->entries; ++lcv) {			(char *)(new->order[lcv]) += (char *)new - (char *)old;		}	}	return new;}/* * init_layout() */static inline void init_layout(struct hfs_hdr_layout *layout,			       const hfs_byte_t *descrs){	struct hfs_hdr_descr **base, **p, **q, *tmp;	int lcv, entries = layout->entries;	for (lcv = 0; lcv < entries; ++lcv, descrs += 12) {		layout->order[lcv] = &layout->descr[lcv];		layout->descr[lcv].id     = hfs_get_hl(descrs);		layout->descr[lcv].offset = hfs_get_hl(descrs + 4);		layout->descr[lcv].length = hfs_get_hl(descrs + 8);	}	for (lcv = layout->entries; lcv < HFS_HDR_MAX; ++lcv) {		layout->order[lcv] = NULL;		layout->descr[lcv].id     = 0;		layout->descr[lcv].offset = 0;		layout->descr[lcv].length = 0;	}	/* Sort the 'order' array using an insertion sort */	base = &layout->order[0];	for (p = (base+1); p < (base+entries); ++p) {		q=p;		while ((*q)->offset < (*(q-1))->offset) {			tmp = *q;			*q = *(q-1);			*(--q) = tmp;			if (q == base) break;		}	}}/* * adjust_forks() */static inline void adjust_forks(struct hfs_cat_entry *entry,				const struct hfs_hdr_layout *layout){	int lcv;	for (lcv = 0; lcv < layout->entries; ++lcv) {		const struct hfs_hdr_descr *descr = &layout->descr[lcv];		if ((descr->id == HFS_HDR_DATA) &&		    (descr->length != entry->u.file.data_fork.lsize)) {			entry->u.file.data_fork.lsize = descr->length;			hfs_extent_adj(&entry->u.file.data_fork);		} else if ((descr->id == HFS_HDR_RSRC) &&			   (descr->length != entry->u.file.rsrc_fork.lsize)) {			entry->u.file.rsrc_fork.lsize = descr->length;			hfs_extent_adj(&entry->u.file.rsrc_fork);		}	}}/* * get_dates() */static void get_dates(const struct hfs_cat_entry *entry,		      const struct inode *inode,  hfs_u32 dates[3]){	dates[0] = hfs_m_to_htime(entry->create_date);	dates[1] = hfs_m_to_htime(entry->modify_date);	dates[2] = hfs_m_to_htime(entry->backup_date);}/* * set_dates() */static void set_dates(struct hfs_cat_entry *entry, struct inode *inode,		      const hfs_u32 *dates){	hfs_u32 tmp;	tmp = hfs_h_to_mtime(dates[0]);	if (entry->create_date != tmp) {		entry->create_date = tmp;		hfs_cat_mark_dirty(entry);	}	tmp = hfs_h_to_mtime(dates[1]);	if (entry->modify_date != tmp) {		entry->modify_date = tmp;		inode->i_ctime = inode->i_atime = inode->i_mtime = 			hfs_h_to_utime(dates[1]);		hfs_cat_mark_dirty(entry);	}	tmp = hfs_h_to_mtime(dates[2]);	if (entry->backup_date != tmp) {		entry->backup_date = tmp;		hfs_cat_mark_dirty(entry);	}}loff_t hdr_llseek(struct file *file, loff_t offset, int origin){	long long retval;	switch (origin) {		case 2:			offset += file->f_dentry->d_inode->i_size;			break;		case 1:			offset += file->f_pos;	}	retval = -EINVAL;	if (offset>=0 && offset<file->f_dentry->d_inode->i_size) {		if (offset != file->f_pos) {			file->f_pos = offset;			file->f_reada = 0;			file->f_version = ++event;		}		retval = offset;	}	return retval;}/* * hdr_read() * * This is the read field in the inode_operations structure for * header files.  The purpose is to transfer up to 'count' bytes * from the file corresponding to 'inode', beginning at * 'filp->offset' bytes into the file.	The data is transferred to * user-space at the address 'buf'.  Returns the number of bytes * successfully transferred. *//* XXX: what about the entry count changing on us? */static hfs_rwret_t hdr_read(struct file * filp, char * buf, 			    hfs_rwarg_t count, loff_t *ppos){	struct inode *inode = filp->f_dentry->d_inode;	struct hfs_cat_entry *entry = HFS_I(inode)->entry;	const struct hfs_hdr_layout *layout;	off_t start, length, offset;	off_t pos = *ppos;	int left, lcv, read = 0;	if (!S_ISREG(inode->i_mode)) {		hfs_warn("hfs_hdr_read: mode = %07o\n",inode->i_mode);		return -EINVAL;	}	if (HFS_I(inode)->layout) {		layout = HFS_I(inode)->layout;	} else {		layout = HFS_I(inode)->default_layout;	}	/* Adjust count to fit within the bounds of the file */	if ((pos >= inode->i_size) || (count <= 0)) {		return 0;	} else if (count > inode->i_size - pos) {		count = inode->i_size - pos;	}	/* Handle the fixed-location portion */	length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 +		 sizeof(hfs_u16) + layout->entries * (3 * sizeof(hfs_u32));	if (pos < length) {		struct hdr_hdr meta;		left = length - pos;		if (left > count) {			left = count;		}		hdr_build_meta(&meta, layout, entry);		left -= copy_to_user(buf, ((char *)&meta) + pos, left);		count -= left;		read += left;		pos += left;		buf += left;	}	if (!count) {		goto done;	}	/* Handle the actual data */	for (lcv = 0; count && (lcv < layout->entries); ++lcv) {		const struct hfs_hdr_descr *descr = layout->order[lcv];		struct hfs_fork *fork;		char tmp[16], *p;		off_t limit;		/* stop reading if we run out of descriptors early */		if (!descr) {			break;		}		/* find start and length of this entry */		start = descr->offset;		length = dlength(descr, entry);		/* Skip to next entry if this one is empty or isn't needed */		if (!length || (pos >= start + length)) {			continue;		}		/* Pad with zeros to the start of this entry if needed */		if (pos < start) {			left = start - pos;			if (left > count) {				left = count;			}			clear_user(buf, left);			count -= left;			read += left;			pos += left;			buf += left;		}		if (!count) {			goto done;		}		/* locate and/or construct the data for this entry */		fork = NULL;		p = NULL;		switch (descr->id) {		case HFS_HDR_DATA:			fork = &entry->u.file.data_fork;			limit = fork->lsize;			break;		case HFS_HDR_RSRC:			fork = &entry->u.file.rsrc_fork;			limit = fork->lsize;			break;		case HFS_HDR_FNAME:			p = entry->key.CName.Name;			limit = entry->key.CName.Len;			break;		case HFS_HDR_OLDI:		case HFS_HDR_DATES:			get_dates(entry, inode, (hfs_u32 *)tmp);			if (descr->id == HFS_HDR_DATES) {				/* XXX: access date. hfsplus actually                                   has this. */				memcpy(tmp + 12, tmp + 4, 4);			} else if ((entry->type == HFS_CDR_FIL) &&				   (entry->u.file.flags & HFS_FIL_LOCK)) {				hfs_put_hl(HFS_AFP_RDONLY, tmp + 12);			} else {				hfs_put_nl(0, tmp + 12);			}			p = tmp;			limit = 16;			break;		case HFS_HDR_FINFO:			p = (char *)&entry->info;			limit = 32;			break;		case HFS_HDR_AFPI:			/* XXX: this needs to do more mac->afp mappings */			hfs_put_ns(0, tmp);			if ((entry->type == HFS_CDR_FIL) &&			    (entry->u.file.flags & HFS_FIL_LOCK)) {				hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);			} else {				hfs_put_ns(0, tmp + 2);

⌨️ 快捷键说明

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