File: /usr/src/linux/fs/hfs/file_hdr.c

1     /*
2      * linux/fs/hfs/file_hdr.c
3      *
4      * Copyright (C) 1995-1997  Paul H. Hargrove
5      * This file may be distributed under the terms of the GNU General Public License.
6      *
7      * This file contains the file_ops and inode_ops for the metadata
8      * files under the AppleDouble and Netatalk representations.
9      *
10      * The source code distributions of Netatalk, versions 1.3.3b2 and
11      * 1.4b2, were used as a specification of the location and format of
12      * files used by Netatalk's afpd.  No code from Netatalk appears in
13      * hfs_fs.  hfs_fs is not a work ``derived'' from Netatalk in the
14      * sense of intellectual property law.
15      *
16      * "XXX" in a comment is a note to myself to consider changing something.
17      *
18      * In function preconditions the term "valid" applied to a pointer to
19      * a structure means that the pointer is non-NULL and the structure it
20      * points to has all fields initialized to consistent values.
21      *
22      * XXX: Note the reason that there is not bmap() for AppleDouble
23      * header files is that dynamic nature of their structure make it
24      * very difficult to safely mmap them.  Maybe in the distant future
25      * I'll get bored enough to implement it.
26      */
27     
28     #include "hfs.h"
29     #include <linux/hfs_fs_sb.h>
30     #include <linux/hfs_fs_i.h>
31     #include <linux/hfs_fs.h>
32     
33     /* prodos types */
34     #define PRODOSI_FTYPE_DIR   0x0F
35     #define PRODOSI_FTYPE_TEXT  0x04
36     #define PRODOSI_FTYPE_8BIT  0xFF
37     #define PRODOSI_FTYPE_16BIT 0xB3
38     
39     #define PRODOSI_AUXTYPE_DIR 0x0200
40     
41     /*================ Forward declarations ================*/
42     static loff_t      hdr_llseek(struct file *, loff_t, int);
43     static hfs_rwret_t hdr_read(struct file *, char *, hfs_rwarg_t, loff_t *);
44     static hfs_rwret_t hdr_write(struct file *, const char *,
45     			     hfs_rwarg_t, loff_t *);
46     /*================ Global variables ================*/
47     
48     struct file_operations hfs_hdr_operations = {
49     	llseek:		hdr_llseek,
50     	read:		hdr_read,
51     	write:		hdr_write,
52     	fsync:		file_fsync,
53     };
54     
55     struct inode_operations hfs_hdr_inode_operations = {
56     	setattr:	hfs_notify_change_hdr,
57     };
58     
59     const struct hfs_hdr_layout hfs_dbl_fil_hdr_layout = {
60     	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
61     	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
62     	6,					/* entries */
63     	{					/* descr[] */
64     		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
65     		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
66     		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
67     		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},
68     		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4},
69     		{HFS_HDR_RSRC,  HFS_DBL_HDR_LEN,                           ~0}
70     	},
71     	{					/* order[] */
72     		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[0],
73     		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[1],
74     		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[2],
75     		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[3],
76     		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[4],
77     		(struct hfs_hdr_descr *)&hfs_dbl_fil_hdr_layout.descr[5]
78     	}
79     };
80     
81     const struct hfs_hdr_layout hfs_dbl_dir_hdr_layout = {
82     	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
83     	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
84     	5,					/* entries */
85     	{					/* descr[] */
86     		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
87     		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
88     		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
89     		{HFS_HDR_MACI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},
90     		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4}
91     	},
92     	{					/* order[] */
93     		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[0],
94     		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[1],
95     		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[2],
96     		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[3],
97     		(struct hfs_hdr_descr *)&hfs_dbl_dir_hdr_layout.descr[4]
98     	}
99     };
100     
101     const struct hfs_hdr_layout hfs_nat2_hdr_layout = {
102     	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
103     	__constant_htonl(HFS_HDR_VERSION_2),	/* version */
104     	9,					/* entries */
105     	{					/* descr[] */
106     		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
107     		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},
108     		{HFS_HDR_DATES, offsetof(struct hfs_dbl_hdr, create_time), 16},
109     		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
110     		{HFS_HDR_AFPI,  offsetof(struct hfs_dbl_hdr, fileinfo),     4},
111     		{HFS_HDR_DID,   offsetof(struct hfs_dbl_hdr, cnid),         4},
112     		{HFS_HDR_SNAME,  offsetof(struct hfs_dbl_hdr, short_name), ~0},
113     		{HFS_HDR_PRODOSI,  offsetof(struct hfs_dbl_hdr, prodosi),   8},
114     		{HFS_HDR_RSRC,  HFS_NAT_HDR_LEN,                           ~0}
115     	},
116     	{					/* order[] */
117     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
118     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
119     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
120     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
121     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4],
122     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[5],
123     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[6],
124     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[7],
125     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[8]
126     	}
127     };
128     
129     const struct hfs_hdr_layout hfs_nat_hdr_layout = {
130     	__constant_htonl(HFS_DBL_MAGIC),	/* magic   */
131     	__constant_htonl(HFS_HDR_VERSION_1),	/* version */
132     	5,					/* entries */
133     	{					/* descr[] */
134     		{HFS_HDR_FNAME, offsetof(struct hfs_dbl_hdr, real_name),   ~0},
135     		{HFS_HDR_COMNT, offsetof(struct hfs_dbl_hdr, comment),      0},
136     		{HFS_HDR_OLDI,  offsetof(struct hfs_dbl_hdr, create_time), 16},
137     		{HFS_HDR_FINFO, offsetof(struct hfs_dbl_hdr, finderinfo),  32},
138     		{HFS_HDR_RSRC,  HFS_NAT_HDR_LEN,                           ~0},
139     	},
140     	{					/* order[] */
141     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[0],
142     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[1],
143     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[2],
144     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[3],
145     		(struct hfs_hdr_descr *)&hfs_nat_hdr_layout.descr[4]
146     	}
147     };
148     
149     /*================ File-local variables ================*/
150     
151     static const char fstype[16] =
152     	{'M','a','c','i','n','t','o','s','h',' ',' ',' ',' ',' ',' ',' '};
153     
154     /*================ File-local data types ================*/
155     
156     struct hdr_hdr {
157             hfs_lword_t	magic;
158             hfs_lword_t	version;
159             hfs_byte_t	filler[16];
160             hfs_word_t	entries;
161             hfs_byte_t	descrs[12*HFS_HDR_MAX];
162     }  __attribute__((packed));
163     
164     /*================ File-local functions ================*/
165     
166     /*
167      * dlength()
168      */
169     static int dlength(const struct hfs_hdr_descr *descr,
170     		   const struct hfs_cat_entry *entry)
171     {
172     	hfs_u32 length = descr->length;
173     
174     	/* handle auto-sized entries */
175     	if (length == ~0) {
176     		switch (descr->id) {
177     		case HFS_HDR_DATA:
178     			if (entry->type == HFS_CDR_FIL) {
179     				length = entry->u.file.data_fork.lsize;
180     			} else {
181     				length = 0;
182     			}
183     			break;
184     
185     		case HFS_HDR_RSRC:
186     			if (entry->type == HFS_CDR_FIL) {
187     				length = entry->u.file.rsrc_fork.lsize;
188     			} else {
189     				length = 0;
190     			}
191     			break;
192     
193     		case HFS_HDR_FNAME:
194     			length = entry->key.CName.Len;
195     			break;
196     
197     		case HFS_HDR_SNAME:
198     		default:
199     			length = 0;
200     		}
201     	}
202     	return length;
203     }
204     
205     /*
206      * hdr_build_meta()
207      */
208     static void hdr_build_meta(struct hdr_hdr *meta,
209     			   const struct hfs_hdr_layout *layout,
210     			   const struct hfs_cat_entry *entry)
211     {
212     	const struct hfs_hdr_descr *descr;
213     	hfs_byte_t *ptr;
214     	int lcv;
215     
216     	hfs_put_nl(layout->magic,   meta->magic);
217     	hfs_put_nl(layout->version, meta->version);
218     	if (layout->version == htonl(HFS_HDR_VERSION_1)) {
219     		memcpy(meta->filler, fstype, 16);
220     	} else {
221     		memset(meta->filler, 0, 16);
222     	}
223     	hfs_put_hs(layout->entries, meta->entries);
224     	memset(meta->descrs, 0, sizeof(meta->descrs));
225     	for (lcv = 0, descr = layout->descr, ptr = meta->descrs;
226     	     lcv < layout->entries; ++lcv, ++descr, ptr += 12) {
227     		hfs_put_hl(descr->id,             ptr);
228     		hfs_put_hl(descr->offset,         ptr + 4);
229     		hfs_put_hl(dlength(descr, entry), ptr + 8);
230     	}
231     }
232     
233     /*
234      * dup_layout ()
235      */
236     static struct hfs_hdr_layout *dup_layout(const struct hfs_hdr_layout *old)
237     {
238     	struct hfs_hdr_layout *new;
239     	int lcv;
240     
241     	if (HFS_NEW(new)) {
242     		memcpy(new, old, sizeof(*new));
243     		for (lcv = 0; lcv < new->entries; ++lcv) {
244     			(char *)(new->order[lcv]) += (char *)new - (char *)old;
245     		}
246     	}
247     	return new;
248     }
249     
250     /*
251      * init_layout()
252      */
253     static inline void init_layout(struct hfs_hdr_layout *layout,
254     			       const hfs_byte_t *descrs)
255     {
256     	struct hfs_hdr_descr **base, **p, **q, *tmp;
257     	int lcv, entries = layout->entries;
258     
259     	for (lcv = 0; lcv < entries; ++lcv, descrs += 12) {
260     		layout->order[lcv] = &layout->descr[lcv];
261     		layout->descr[lcv].id     = hfs_get_hl(descrs);
262     		layout->descr[lcv].offset = hfs_get_hl(descrs + 4);
263     		layout->descr[lcv].length = hfs_get_hl(descrs + 8);
264     	}
265     	for (lcv = layout->entries; lcv < HFS_HDR_MAX; ++lcv) {
266     		layout->order[lcv] = NULL;
267     		layout->descr[lcv].id     = 0;
268     		layout->descr[lcv].offset = 0;
269     		layout->descr[lcv].length = 0;
270     	}
271     
272     	/* Sort the 'order' array using an insertion sort */
273     	base = &layout->order[0];
274     	for (p = (base+1); p < (base+entries); ++p) {
275     		q=p;
276     		while ((*q)->offset < (*(q-1))->offset) {
277     			tmp = *q;
278     			*q = *(q-1);
279     			*(--q) = tmp;
280     			if (q == base) break;
281     		}
282     	}
283     }
284     
285     /*
286      * adjust_forks()
287      */
288     static inline void adjust_forks(struct hfs_cat_entry *entry,
289     				const struct hfs_hdr_layout *layout)
290     {
291     	int lcv;
292     
293     	for (lcv = 0; lcv < layout->entries; ++lcv) {
294     		const struct hfs_hdr_descr *descr = &layout->descr[lcv];
295     
296     		if ((descr->id == HFS_HDR_DATA) &&
297     		    (descr->length != entry->u.file.data_fork.lsize)) {
298     			entry->u.file.data_fork.lsize = descr->length;
299     			hfs_extent_adj(&entry->u.file.data_fork);
300     		} else if ((descr->id == HFS_HDR_RSRC) &&
301     			   (descr->length != entry->u.file.rsrc_fork.lsize)) {
302     			entry->u.file.rsrc_fork.lsize = descr->length;
303     			hfs_extent_adj(&entry->u.file.rsrc_fork);
304     		}
305     	}
306     }
307     
308     /*
309      * get_dates()
310      */
311     static void get_dates(const struct hfs_cat_entry *entry,
312     		      const struct inode *inode,  hfs_u32 dates[3])
313     {
314     	dates[0] = hfs_m_to_htime(entry->create_date);
315     	dates[1] = hfs_m_to_htime(entry->modify_date);
316     	dates[2] = hfs_m_to_htime(entry->backup_date);
317     }
318     
319     /*
320      * set_dates()
321      */
322     static void set_dates(struct hfs_cat_entry *entry, struct inode *inode,
323     		      const hfs_u32 *dates)
324     {
325     	hfs_u32 tmp;
326     
327     	tmp = hfs_h_to_mtime(dates[0]);
328     	if (entry->create_date != tmp) {
329     		entry->create_date = tmp;
330     		hfs_cat_mark_dirty(entry);
331     	}
332     	tmp = hfs_h_to_mtime(dates[1]);
333     	if (entry->modify_date != tmp) {
334     		entry->modify_date = tmp;
335     		inode->i_ctime = inode->i_atime = inode->i_mtime = 
336     			hfs_h_to_utime(dates[1]);
337     		hfs_cat_mark_dirty(entry);
338     	}
339     	tmp = hfs_h_to_mtime(dates[2]);
340     	if (entry->backup_date != tmp) {
341     		entry->backup_date = tmp;
342     		hfs_cat_mark_dirty(entry);
343     	}
344     }
345     
346     loff_t hdr_llseek(struct file *file, loff_t offset, int origin)
347     {
348     	long long retval;
349     
350     	switch (origin) {
351     		case 2:
352     			offset += file->f_dentry->d_inode->i_size;
353     			break;
354     		case 1:
355     			offset += file->f_pos;
356     	}
357     	retval = -EINVAL;
358     	if (offset>=0 && offset<file->f_dentry->d_inode->i_size) {
359     		if (offset != file->f_pos) {
360     			file->f_pos = offset;
361     			file->f_reada = 0;
362     			file->f_version = ++event;
363     		}
364     		retval = offset;
365     	}
366     	return retval;
367     }
368     
369     /*
370      * hdr_read()
371      *
372      * This is the read field in the inode_operations structure for
373      * header files.  The purpose is to transfer up to 'count' bytes
374      * from the file corresponding to 'inode', beginning at
375      * 'filp->offset' bytes into the file.	The data is transferred to
376      * user-space at the address 'buf'.  Returns the number of bytes
377      * successfully transferred.
378      */
379     /* XXX: what about the entry count changing on us? */
380     static hfs_rwret_t hdr_read(struct file * filp, char * buf, 
381     			    hfs_rwarg_t count, loff_t *ppos)
382     {
383     	struct inode *inode = filp->f_dentry->d_inode;
384     	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
385     	const struct hfs_hdr_layout *layout;
386     	off_t start, length, offset;
387     	off_t pos = *ppos;
388     	int left, lcv, read = 0;
389     
390     	if (!S_ISREG(inode->i_mode)) {
391     		hfs_warn("hfs_hdr_read: mode = %07o\n",inode->i_mode);
392     		return -EINVAL;
393     	}
394     
395     	if (HFS_I(inode)->layout) {
396     		layout = HFS_I(inode)->layout;
397     	} else {
398     		layout = HFS_I(inode)->default_layout;
399     	}
400     
401     	/* Adjust count to fit within the bounds of the file */
402     	if ((pos >= inode->i_size) || (count <= 0)) {
403     		return 0;
404     	} else if (count > inode->i_size - pos) {
405     		count = inode->i_size - pos;
406     	}
407     
408     	/* Handle the fixed-location portion */
409     	length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 +
410     		 sizeof(hfs_u16) + layout->entries * (3 * sizeof(hfs_u32));
411     	if (pos < length) {
412     		struct hdr_hdr meta;
413     
414     		left = length - pos;
415     		if (left > count) {
416     			left = count;
417     		}
418     
419     		hdr_build_meta(&meta, layout, entry);
420     		left -= copy_to_user(buf, ((char *)&meta) + pos, left);
421     		count -= left;
422     		read += left;
423     		pos += left;
424     		buf += left;
425     	}
426     	if (!count) {
427     		goto done;
428     	}
429     
430     	/* Handle the actual data */
431     	for (lcv = 0; count && (lcv < layout->entries); ++lcv) {
432     		const struct hfs_hdr_descr *descr = layout->order[lcv];
433     		struct hfs_fork *fork;
434     		char tmp[16], *p;
435     		off_t limit;
436     
437     		/* stop reading if we run out of descriptors early */
438     		if (!descr) {
439     			break;
440     		}
441     
442     		/* find start and length of this entry */
443     		start = descr->offset;
444     		length = dlength(descr, entry);
445     
446     		/* Skip to next entry if this one is empty or isn't needed */
447     		if (!length || (pos >= start + length)) {
448     			continue;
449     		}
450     
451     		/* Pad with zeros to the start of this entry if needed */
452     		if (pos < start) {
453     			left = start - pos;
454     			if (left > count) {
455     				left = count;
456     			}
457     			clear_user(buf, left);
458     			count -= left;
459     			read += left;
460     			pos += left;
461     			buf += left;
462     		}
463     		if (!count) {
464     			goto done;
465     		}
466     
467     		/* locate and/or construct the data for this entry */
468     		fork = NULL;
469     		p = NULL;
470     		switch (descr->id) {
471     		case HFS_HDR_DATA:
472     			fork = &entry->u.file.data_fork;
473     			limit = fork->lsize;
474     			break;
475     
476     		case HFS_HDR_RSRC:
477     			fork = &entry->u.file.rsrc_fork;
478     			limit = fork->lsize;
479     			break;
480     
481     		case HFS_HDR_FNAME:
482     			p = entry->key.CName.Name;
483     			limit = entry->key.CName.Len;
484     			break;
485     
486     		case HFS_HDR_OLDI:
487     		case HFS_HDR_DATES:
488     			get_dates(entry, inode, (hfs_u32 *)tmp);
489     			if (descr->id == HFS_HDR_DATES) {
490     				/* XXX: access date. hfsplus actually
491                                        has this. */
492     				memcpy(tmp + 12, tmp + 4, 4);
493     			} else if ((entry->type == HFS_CDR_FIL) &&
494     				   (entry->u.file.flags & HFS_FIL_LOCK)) {
495     				hfs_put_hl(HFS_AFP_RDONLY, tmp + 12);
496     			} else {
497     				hfs_put_nl(0, tmp + 12);
498     			}
499     			p = tmp;
500     			limit = 16;
501     			break;
502     
503     		case HFS_HDR_FINFO:
504     			p = (char *)&entry->info;
505     			limit = 32;
506     			break;
507     
508     		case HFS_HDR_AFPI:
509     			/* XXX: this needs to do more mac->afp mappings */
510     			hfs_put_ns(0, tmp);
511     			if ((entry->type == HFS_CDR_FIL) &&
512     			    (entry->u.file.flags & HFS_FIL_LOCK)) {
513     				hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
514     			} else {
515     				hfs_put_ns(0, tmp + 2);
516     			}
517     			p = tmp;
518     			limit = 4;
519     		        break;
520     
521     		case HFS_HDR_PRODOSI:
522     			/* XXX: this needs to do mac->prodos translations */
523     			memset(tmp, 0, 8);
524     #if 0
525     			hfs_put_ns(0, tmp); /* access */
526     			hfs_put_ns(0, tmp); /* type */
527     			hfs_put_nl(0, tmp); /* aux type */
528     #endif
529     			p = tmp;
530     			limit = 8;
531     		        break;
532     
533     		case HFS_HDR_MACI:
534     			hfs_put_ns(0, tmp);
535     			if (entry->type == HFS_CDR_FIL) {
536     				hfs_put_hs(entry->u.file.flags, tmp + 2);
537     			} else {
538     				hfs_put_ns(entry->u.dir.flags, tmp + 2);
539     			}
540     			p = tmp;
541     			limit = 4;
542     			break;
543     
544     		case HFS_HDR_DID:
545     		        /* if it's rootinfo, stick the next available did in
546     			 * the did slot. */
547     			limit = 4;
548     			if (entry->cnid == htonl(HFS_ROOT_CNID)) {
549     				struct hfs_mdb *mdb = entry->mdb;
550     				const struct hfs_name *reserved = 
551     				HFS_SB(mdb->sys_mdb)->s_reserved2;
552     				
553     				while (reserved->Len) {
554     					if (hfs_streq(reserved->Name,
555     						      reserved->Len,
556     						      entry->key.CName.Name,
557     						      entry->key.CName.Len)) {
558     						hfs_put_hl(mdb->next_id, tmp);
559     						p = tmp;
560     						goto hfs_did_done;
561     					}
562     					reserved++;
563     				}
564     			}
565     			p = (char *) &entry->cnid;
566     hfs_did_done:
567     			break;
568     
569     		case HFS_HDR_SNAME:
570     		default:
571     			limit = 0;
572     		}
573     		
574     		/* limit the transfer to the available data
575     		   of to the stated length of the entry. */
576     		if (length > limit) {
577     			length = limit;
578     		}
579     		offset = pos - start;
580     		left = length - offset;
581     		if (left > count) {
582     			left = count;
583     		}
584     		if (left <= 0) {
585     			continue;
586     		}
587     
588     		/* transfer the data */
589     		if (p) {
590     			left -= copy_to_user(buf, p + offset, left);
591     		} else if (fork) {
592     			left = hfs_do_read(inode, fork, offset, buf, left,
593     					   filp->f_reada != 0);
594     			if (left > 0) {
595     				filp->f_reada = 1;
596     			} else if (!read) {
597     				return left;
598     			} else {
599     				goto done;
600     			}
601     		}
602     		count -= left;
603     		read += left;
604     		pos += left;
605     		buf += left;
606     	}
607     
608     	/* Pad the file out with zeros */
609     	if (count) {
610     		clear_user(buf, count);
611     		read += count;
612     		pos += count;
613     	}
614     		
615     done:
616     	if (read) {
617     		inode->i_atime = CURRENT_TIME;
618     		*ppos = pos;
619     		mark_inode_dirty(inode);
620     	}
621     	return read;
622     }
623     
624     /*
625      * hdr_write()
626      *
627      * This is the write() entry in the file_operations structure for
628      * header files.  The purpose is to transfer up to 'count' bytes
629      * to the file corresponding to 'inode' beginning at offset
630      * '*ppos' from user-space at the address 'buf'.
631      * The return value is the number of bytes actually transferred.
632      */
633     static hfs_rwret_t hdr_write(struct file *filp, const char *buf,
634     			     hfs_rwarg_t count, loff_t *ppos)
635     {
636     	struct inode *inode = filp->f_dentry->d_inode;
637             struct hfs_cat_entry *entry = HFS_I(inode)->entry;
638             struct hfs_hdr_layout *layout;
639             off_t start, length, offset;
640             int left, lcv, written = 0;
641     	struct hdr_hdr meta;
642     	int built_meta = 0;
643             off_t pos;
644     
645     	if (!S_ISREG(inode->i_mode)) {
646     		hfs_warn("hfs_hdr_write: mode = %07o\n", inode->i_mode);
647     		return -EINVAL;
648     	}
649     	if (count <= 0) {
650     		return 0;
651     	}
652     
653     	pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
654     
655     	if (!HFS_I(inode)->layout) {
656     		HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);
657     	}
658     	layout = HFS_I(inode)->layout;
659     
660     	/* Handle the 'magic', 'version', 'filler' and 'entries' fields */
661     	length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 + sizeof(hfs_u16);
662     	if (pos < length) {
663     		hdr_build_meta(&meta, layout, entry);
664     		built_meta = 1;
665     
666     		left = length - pos;
667     		if (left > count) {
668     			left = count;
669     		}
670     
671     		left -= copy_from_user(((char *)&meta) + pos, buf, left);
672     		layout->magic   = hfs_get_nl(meta.magic);
673     		layout->version = hfs_get_nl(meta.version);
674     		layout->entries = hfs_get_hs(meta.entries);
675     		if (layout->entries > HFS_HDR_MAX) {
676     			/* XXX: should allocate slots dynamically */
677     			hfs_warn("hfs_hdr_write: TRUNCATING TO %d "
678     				 "DESCRIPTORS\n", HFS_HDR_MAX);
679     			layout->entries = HFS_HDR_MAX;
680     		}
681     
682     		count -= left;
683     		written += left;
684     		pos += left;
685     		buf += left;
686     	}
687     	if (!count) {
688     		goto done;
689     	}
690     
691     	/* We know for certain how many entries we have, so process them */
692     	length += layout->entries * 3 * sizeof(hfs_u32);
693     	if (pos < length) {
694     		if (!built_meta) {
695     			hdr_build_meta(&meta, layout, entry);
696     		}
697     
698     		left = length - pos;
699     		if (left > count) {
700     			left = count;
701     		}
702     
703     		left -= copy_from_user(((char *)&meta) + pos, buf, left);
704     		init_layout(layout, meta.descrs);
705     
706     		count -= left;
707     		written += left;
708     		pos += left;
709     		buf += left;
710     
711     		/* Handle possible size changes for the forks */
712     		if (entry->type == HFS_CDR_FIL) {
713     			adjust_forks(entry, layout);
714     			hfs_cat_mark_dirty(entry);
715     		}
716     	}
717     
718     	/* Handle the actual data */
719     	for (lcv = 0; count && (lcv < layout->entries); ++lcv) {
720     		struct hfs_hdr_descr *descr = layout->order[lcv];
721     		struct hfs_fork *fork;
722     		char tmp[16], *p;
723     		off_t limit;
724     
725     		/* stop writing if we run out of descriptors early */
726     		if (!descr) {
727     			break;
728     		}
729     
730     		/* find start and length of this entry */
731     		start = descr->offset;
732     		if ((descr->id == HFS_HDR_DATA) ||
733     		    (descr->id == HFS_HDR_RSRC)) {
734     			if (entry->type == HFS_CDR_FIL) {
735     				length = 0x7fffffff - start;
736     			} else {
737     				continue;
738     			}
739     		} else {
740     			length = dlength(descr, entry);
741     		}
742     
743     		/* Trim length to avoid overlap with the next entry */
744     		if (layout->order[lcv+1] &&
745     		    ((start + length) > layout->order[lcv+1]->offset)) {
746     			length = layout->order[lcv+1]->offset - start;
747     		}
748     
749     		/* Skip to next entry if this one is empty or isn't needed */
750     		if (!length || (pos >= start + length)) {
751     			continue;
752     		}
753     
754     		/* Skip any padding that may exist between entries */
755     		if (pos < start) {
756     			left = start - pos;
757     			if (left > count) {
758     				left = count;
759     			}
760     			count -= left;
761     			written += left;
762     			pos += left;
763     			buf += left;
764     		}
765     		if (!count) {
766     			goto done;
767     		}
768     
769     		/* locate and/or construct the data for this entry */
770     		fork = NULL;
771     		p = NULL;
772     		switch (descr->id) {
773     		case HFS_HDR_DATA:
774     #if 0
775     /* Can't yet write to the data fork via a header file, since there is the
776      * possibility to write via the data file, and the only locking is at the
777      * inode level.
778      */
779     			fork = &entry->u.file.data_fork;
780     			limit = length;
781     #else
782     			limit = 0;
783     #endif
784     			break;
785     
786     		case HFS_HDR_RSRC:
787     			fork = &entry->u.file.rsrc_fork;
788     			limit = length;
789     			break;
790     
791     		case HFS_HDR_OLDI:
792     		case HFS_HDR_DATES:
793     			get_dates(entry, inode, (hfs_u32 *)tmp);
794     			if (descr->id == HFS_HDR_DATES) {
795     				memcpy(tmp + 12, tmp + 4, 4);
796     			} else if ((entry->type == HFS_CDR_FIL) &&
797     				   (entry->u.file.flags & HFS_FIL_LOCK)) {
798     				hfs_put_hl(HFS_AFP_RDONLY, tmp + 12);
799     			} else {
800     				hfs_put_nl(0, tmp + 12);
801     			}
802     			p = tmp;
803     			limit = 16;
804     			break;
805     
806     		case HFS_HDR_FINFO:
807     			p = (char *)&entry->info;
808     			limit = 32;
809     			break;
810     
811     		case HFS_HDR_AFPI:
812     			hfs_put_ns(0, tmp);
813     			if ((entry->type == HFS_CDR_FIL) &&
814     			    (entry->u.file.flags & HFS_FIL_LOCK)) {
815     				hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
816     			} else {
817     				hfs_put_ns(0, tmp + 2);
818     			}			
819     			p = tmp;
820     			limit = 4;
821     			break;
822     
823     		case HFS_HDR_PRODOSI:
824     			/* XXX: this needs to do mac->prodos translations */
825     			memset(tmp, 0, 8); 
826     #if 0
827     			hfs_put_ns(0, tmp); /* access */
828     			hfs_put_ns(0, tmp); /* type */
829     			hfs_put_nl(0, tmp); /* aux type */
830     #endif
831     			p = tmp;
832     			limit = 8;
833     		        break;
834     
835     		case HFS_HDR_MACI:
836     			hfs_put_ns(0, tmp);
837     			if (entry->type == HFS_CDR_FIL) {
838     				hfs_put_hs(entry->u.file.flags, tmp + 2);
839     			} else {
840     				hfs_put_ns(entry->u.dir.flags, tmp + 2);
841     			}
842     			p = tmp;
843     			limit = 4;
844     			break;
845     
846     		case HFS_HDR_FNAME:	/* Can't rename a file this way */
847     		case HFS_HDR_DID:       /* can't specify a did this way */
848     		default:
849     			limit = 0;
850     		}
851     		
852     		/* limit the transfer to the available data
853     		   of to the stated length of the entry. */
854     		if (length > limit) {
855     			length = limit;
856     		}
857     		offset = pos - start;
858     		left = length - offset;
859     		if (left > count) {
860     			left = count;
861     		}
862     		if (left <= 0) {
863     			continue;
864     		}
865     
866     		/* transfer the data from user space */
867     		if (p) {
868     			left -= copy_from_user(p + offset, buf, left);
869     		} else if (fork) {
870     			left = hfs_do_write(inode, fork, offset, buf, left);
871     		}
872     
873     		/* process the data */
874     		switch (descr->id) {
875     		case HFS_HDR_OLDI:
876     			set_dates(entry, inode, (hfs_u32 *)tmp);
877     			if (entry->type == HFS_CDR_FIL) {
878     				hfs_u8 new_flags = entry->u.file.flags;
879     
880     				if (hfs_get_nl(tmp+12) & htonl(HFS_AFP_WRI)) {
881     					new_flags |= HFS_FIL_LOCK;
882     				} else {
883     					new_flags &= ~HFS_FIL_LOCK;
884     				}
885     
886     				if (new_flags != entry->u.file.flags) {
887     					entry->u.file.flags = new_flags;
888     					hfs_cat_mark_dirty(entry);
889     					hfs_file_fix_mode(entry);
890     				}
891     			}
892     			break;
893     
894     		case HFS_HDR_DATES:
895     			set_dates(entry, inode, (hfs_u32 *)tmp);
896     			break;
897     
898     		case HFS_HDR_FINFO:
899     			hfs_cat_mark_dirty(entry);
900     			break;
901     
902     		case HFS_HDR_MACI:
903     			if (entry->type == HFS_CDR_DIR) {
904     				hfs_u16 new_flags = hfs_get_ns(tmp + 2);
905     
906     				if (entry->u.dir.flags != new_flags) {
907     					entry->u.dir.flags = new_flags;
908     					hfs_cat_mark_dirty(entry);
909     				}
910     			} else {
911     				hfs_u8 new_flags = tmp[3];
912     				hfs_u8 changed = entry->u.file.flags^new_flags;
913     				
914     				if (changed) {
915     					entry->u.file.flags = new_flags;
916     					hfs_cat_mark_dirty(entry);
917     					if (changed & HFS_FIL_LOCK) {
918     						hfs_file_fix_mode(entry);
919     					}
920     				}
921     			}
922     			break;
923     
924     		case HFS_HDR_DATA:
925     		case HFS_HDR_RSRC:
926     			if (left <= 0) {
927     				if (!written) {
928     					return left;
929     				} else {
930     					goto done;
931     				}
932     			} else if (fork->lsize > descr->length) {
933     				descr->length = fork->lsize;
934     			}
935     			break;
936     
937     		case HFS_HDR_FNAME:	/* Can't rename a file this way */
938     		case HFS_HDR_DID:       /* Can't specify a did this way */
939     		case HFS_HDR_PRODOSI:   /* not implemented yet */
940     		case HFS_HDR_AFPI:      /* ditto */
941     		default:
942     			break;
943     		}
944     
945     		count -= left;
946     		written += left;
947     		pos += left;
948     		buf += left;
949     	}
950     
951     	/* Skip any padding at the end */
952     	if (count) {
953     		written += count;
954     		pos += count;
955     	}
956     		
957     done:
958     	*ppos = pos;
959     	if (written > 0) {
960     	        if (pos > inode->i_size)
961     		        inode->i_size = pos;
962     	        inode->i_mtime = inode->i_atime = CURRENT_TIME;
963     		mark_inode_dirty(inode);
964     	}
965     	return written;
966     }
967     
968     /*
969      * hdr_truncate()
970      *
971      * This is the truncate field in the inode_operations structure for
972      * header files.  The purpose is to allocate or release blocks as needed
973      * to satisfy a change in file length.
974      */
975     void hdr_truncate(struct inode *inode, size_t size)
976     {
977     	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
978     	struct hfs_hdr_layout *layout;
979     	int lcv, last;
980     
981     	inode->i_size = size;
982     	if (!HFS_I(inode)->layout) {
983     		HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);
984     	}
985     	layout = HFS_I(inode)->layout;
986     
987     	last = layout->entries - 1;
988     	for (lcv = 0; lcv <= last; ++lcv) {
989     		struct hfs_hdr_descr *descr = layout->order[lcv];
990     		struct hfs_fork *fork;
991     		hfs_u32 offset;
992     
993     		if (!descr) {
994     			break;
995     		}
996     
997     		if (descr->id == HFS_HDR_RSRC) {
998     			fork = &entry->u.file.rsrc_fork;
999     #if 0
1000     /* Can't yet truncate the data fork via a header file, since there is the
1001      * possibility to truncate via the data file, and the only locking is at
1002      * the inode level.
1003      */
1004     		} else if (descr->id == HFS_HDR_DATA) {
1005     			fork = &entry->u.file.data_fork;
1006     #endif
1007     		} else {
1008     			continue;
1009     		}
1010     
1011     		offset = descr->offset;
1012     
1013     		if ((lcv != last) && ((offset + descr->length) <= size)) {
1014     			continue;
1015     		}
1016     
1017     		if (offset < size) {
1018     			descr->length = size - offset;
1019     		} else {
1020     			descr->length = 0;
1021     		}
1022     		if (fork->lsize != descr->length) {
1023     			fork->lsize = descr->length;
1024     			hfs_extent_adj(fork);
1025     			hfs_cat_mark_dirty(entry);
1026     		}
1027     	}
1028     }
1029