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

📄 file_hdr.c

📁 ARM 嵌入式 系统 设计与实例开发 实验教材 二源码
💻 C
📖 第 1 页 / 共 2 页
字号:
			}			p = tmp;			limit = 4;		        break;		case HFS_HDR_PRODOSI:			/* XXX: this needs to do mac->prodos translations */			memset(tmp, 0, 8);#if 0			hfs_put_ns(0, tmp); /* access */			hfs_put_ns(0, tmp); /* type */			hfs_put_nl(0, tmp); /* aux type */#endif			p = tmp;			limit = 8;		        break;		case HFS_HDR_MACI:			hfs_put_ns(0, tmp);			if (entry->type == HFS_CDR_FIL) {				hfs_put_hs(entry->u.file.flags, tmp + 2);			} else {				hfs_put_ns(entry->u.dir.flags, tmp + 2);			}			p = tmp;			limit = 4;			break;		case HFS_HDR_DID:		        /* if it's rootinfo, stick the next available did in			 * the did slot. */			limit = 4;			if (entry->cnid == htonl(HFS_ROOT_CNID)) {				struct hfs_mdb *mdb = entry->mdb;				const struct hfs_name *reserved = 				HFS_SB(mdb->sys_mdb)->s_reserved2;								while (reserved->Len) {					if (hfs_streq(reserved->Name,						      reserved->Len,						      entry->key.CName.Name,						      entry->key.CName.Len)) {						hfs_put_hl(mdb->next_id, tmp);						p = tmp;						goto hfs_did_done;					}					reserved++;				}			}			p = (char *) &entry->cnid;hfs_did_done:			break;		case HFS_HDR_SNAME:		default:			limit = 0;		}				/* limit the transfer to the available data		   of to the stated length of the entry. */		if (length > limit) {			length = limit;		}		offset = pos - start;		left = length - offset;		if (left > count) {			left = count;		}		if (left <= 0) {			continue;		}		/* transfer the data */		if (p) {			left -= copy_to_user(buf, p + offset, left);		} else if (fork) {			left = hfs_do_read(inode, fork, offset, buf, left,					   filp->f_reada != 0);			if (left > 0) {				filp->f_reada = 1;			} else if (!read) {				return left;			} else {				goto done;			}		}		count -= left;		read += left;		pos += left;		buf += left;	}	/* Pad the file out with zeros */	if (count) {		clear_user(buf, count);		read += count;		pos += count;	}		done:	if (read) {		inode->i_atime = CURRENT_TIME;		*ppos = pos;		mark_inode_dirty(inode);	}	return read;}/* * hdr_write() * * This is the write() entry in the file_operations structure for * header files.  The purpose is to transfer up to 'count' bytes * to the file corresponding to 'inode' beginning at offset * '*ppos' from user-space at the address 'buf'. * The return value is the number of bytes actually transferred. */static hfs_rwret_t hdr_write(struct file *filp, const 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;        struct hfs_hdr_layout *layout;        off_t start, length, offset;        int left, lcv, written = 0;	struct hdr_hdr meta;	int built_meta = 0;        off_t pos;	if (!S_ISREG(inode->i_mode)) {		hfs_warn("hfs_hdr_write: mode = %07o\n", inode->i_mode);		return -EINVAL;	}	if (count <= 0) {		return 0;	}	pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;	if (!HFS_I(inode)->layout) {		HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);	}	layout = HFS_I(inode)->layout;	/* Handle the 'magic', 'version', 'filler' and 'entries' fields */	length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 + sizeof(hfs_u16);	if (pos < length) {		hdr_build_meta(&meta, layout, entry);		built_meta = 1;		left = length - pos;		if (left > count) {			left = count;		}		left -= copy_from_user(((char *)&meta) + pos, buf, left);		layout->magic   = hfs_get_nl(meta.magic);		layout->version = hfs_get_nl(meta.version);		layout->entries = hfs_get_hs(meta.entries);		if (layout->entries > HFS_HDR_MAX) {			/* XXX: should allocate slots dynamically */			hfs_warn("hfs_hdr_write: TRUNCATING TO %d "				 "DESCRIPTORS\n", HFS_HDR_MAX);			layout->entries = HFS_HDR_MAX;		}		count -= left;		written += left;		pos += left;		buf += left;	}	if (!count) {		goto done;	}	/* We know for certain how many entries we have, so process them */	length += layout->entries * 3 * sizeof(hfs_u32);	if (pos < length) {		if (!built_meta) {			hdr_build_meta(&meta, layout, entry);		}		left = length - pos;		if (left > count) {			left = count;		}		left -= copy_from_user(((char *)&meta) + pos, buf, left);		init_layout(layout, meta.descrs);		count -= left;		written += left;		pos += left;		buf += left;		/* Handle possible size changes for the forks */		if (entry->type == HFS_CDR_FIL) {			adjust_forks(entry, layout);			hfs_cat_mark_dirty(entry);		}	}	/* Handle the actual data */	for (lcv = 0; count && (lcv < layout->entries); ++lcv) {		struct hfs_hdr_descr *descr = layout->order[lcv];		struct hfs_fork *fork;		char tmp[16], *p;		off_t limit;		/* stop writing if we run out of descriptors early */		if (!descr) {			break;		}		/* find start and length of this entry */		start = descr->offset;		if ((descr->id == HFS_HDR_DATA) ||		    (descr->id == HFS_HDR_RSRC)) {			if (entry->type == HFS_CDR_FIL) {				length = 0x7fffffff - start;			} else {				continue;			}		} else {			length = dlength(descr, entry);		}		/* Trim length to avoid overlap with the next entry */		if (layout->order[lcv+1] &&		    ((start + length) > layout->order[lcv+1]->offset)) {			length = layout->order[lcv+1]->offset - start;		}		/* Skip to next entry if this one is empty or isn't needed */		if (!length || (pos >= start + length)) {			continue;		}		/* Skip any padding that may exist between entries */		if (pos < start) {			left = start - pos;			if (left > count) {				left = count;			}			count -= left;			written += 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:#if 0/* Can't yet write to the data fork via a header file, since there is the * possibility to write via the data file, and the only locking is at the * inode level. */			fork = &entry->u.file.data_fork;			limit = length;#else			limit = 0;#endif			break;		case HFS_HDR_RSRC:			fork = &entry->u.file.rsrc_fork;			limit = length;			break;		case HFS_HDR_OLDI:		case HFS_HDR_DATES:			get_dates(entry, inode, (hfs_u32 *)tmp);			if (descr->id == HFS_HDR_DATES) {				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:			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);			}						p = tmp;			limit = 4;			break;		case HFS_HDR_PRODOSI:			/* XXX: this needs to do mac->prodos translations */			memset(tmp, 0, 8); #if 0			hfs_put_ns(0, tmp); /* access */			hfs_put_ns(0, tmp); /* type */			hfs_put_nl(0, tmp); /* aux type */#endif			p = tmp;			limit = 8;		        break;		case HFS_HDR_MACI:			hfs_put_ns(0, tmp);			if (entry->type == HFS_CDR_FIL) {				hfs_put_hs(entry->u.file.flags, tmp + 2);			} else {				hfs_put_ns(entry->u.dir.flags, tmp + 2);			}			p = tmp;			limit = 4;			break;		case HFS_HDR_FNAME:	/* Can't rename a file this way */		case HFS_HDR_DID:       /* can't specify a did this way */		default:			limit = 0;		}				/* limit the transfer to the available data		   of to the stated length of the entry. */		if (length > limit) {			length = limit;		}		offset = pos - start;		left = length - offset;		if (left > count) {			left = count;		}		if (left <= 0) {			continue;		}		/* transfer the data from user space */		if (p) {			left -= copy_from_user(p + offset, buf, left);		} else if (fork) {			left = hfs_do_write(inode, fork, offset, buf, left);		}		/* process the data */		switch (descr->id) {		case HFS_HDR_OLDI:			set_dates(entry, inode, (hfs_u32 *)tmp);			if (entry->type == HFS_CDR_FIL) {				hfs_u8 new_flags = entry->u.file.flags;				if (hfs_get_nl(tmp+12) & htonl(HFS_AFP_WRI)) {					new_flags |= HFS_FIL_LOCK;				} else {					new_flags &= ~HFS_FIL_LOCK;				}				if (new_flags != entry->u.file.flags) {					entry->u.file.flags = new_flags;					hfs_cat_mark_dirty(entry);					hfs_file_fix_mode(entry);				}			}			break;		case HFS_HDR_DATES:			set_dates(entry, inode, (hfs_u32 *)tmp);			break;		case HFS_HDR_FINFO:			hfs_cat_mark_dirty(entry);			break;		case HFS_HDR_MACI:			if (entry->type == HFS_CDR_DIR) {				hfs_u16 new_flags = hfs_get_ns(tmp + 2);				if (entry->u.dir.flags != new_flags) {					entry->u.dir.flags = new_flags;					hfs_cat_mark_dirty(entry);				}			} else {				hfs_u8 new_flags = tmp[3];				hfs_u8 changed = entry->u.file.flags^new_flags;								if (changed) {					entry->u.file.flags = new_flags;					hfs_cat_mark_dirty(entry);					if (changed & HFS_FIL_LOCK) {						hfs_file_fix_mode(entry);					}				}			}			break;		case HFS_HDR_DATA:		case HFS_HDR_RSRC:			if (left <= 0) {				if (!written) {					return left;				} else {					goto done;				}			} else if (fork->lsize > descr->length) {				descr->length = fork->lsize;			}			break;		case HFS_HDR_FNAME:	/* Can't rename a file this way */		case HFS_HDR_DID:       /* Can't specify a did this way */		case HFS_HDR_PRODOSI:   /* not implemented yet */		case HFS_HDR_AFPI:      /* ditto */		default:			break;		}		count -= left;		written += left;		pos += left;		buf += left;	}	/* Skip any padding at the end */	if (count) {		written += count;		pos += count;	}		done:	*ppos = pos;	if (written > 0) {	        if (pos > inode->i_size)		        inode->i_size = pos;	        inode->i_mtime = inode->i_atime = CURRENT_TIME;		mark_inode_dirty(inode);	}	return written;}/* * hdr_truncate() * * This is the truncate field in the inode_operations structure for * header files.  The purpose is to allocate or release blocks as needed * to satisfy a change in file length. */void hdr_truncate(struct inode *inode, size_t size){	struct hfs_cat_entry *entry = HFS_I(inode)->entry;	struct hfs_hdr_layout *layout;	int lcv, last;	inode->i_size = size;	if (!HFS_I(inode)->layout) {		HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);	}	layout = HFS_I(inode)->layout;	last = layout->entries - 1;	for (lcv = 0; lcv <= last; ++lcv) {		struct hfs_hdr_descr *descr = layout->order[lcv];		struct hfs_fork *fork;		hfs_u32 offset;		if (!descr) {			break;		}		if (descr->id == HFS_HDR_RSRC) {			fork = &entry->u.file.rsrc_fork;#if 0/* Can't yet truncate the data fork via a header file, since there is the * possibility to truncate via the data file, and the only locking is at * the inode level. */		} else if (descr->id == HFS_HDR_DATA) {			fork = &entry->u.file.data_fork;#endif		} else {			continue;		}		offset = descr->offset;		if ((lcv != last) && ((offset + descr->length) <= size)) {			continue;		}		if (offset < size) {			descr->length = size - offset;		} else {			descr->length = 0;		}		if (fork->lsize != descr->length) {			fork->lsize = descr->length;			hfs_extent_adj(fork);			hfs_cat_mark_dirty(entry);		}	}}

⌨️ 快捷键说明

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