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  */
dlength(const struct hfs_hdr_descr * descr,const struct hfs_cat_entry * entry)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  */
hdr_build_meta(struct hdr_hdr * meta,const struct hfs_hdr_layout * layout,const struct hfs_cat_entry * entry)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  */
dup_layout(const struct hfs_hdr_layout * old)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 			new->order[lcv] = (struct hfs_hdr_descr *)
245 					  ((char *)(new->order[lcv]) +
246 					   ((char *)new - (char *)old));
247 		}
248 	}
249 	return new;
250 }
251 
252 /*
253  * init_layout()
254  */
init_layout(struct hfs_hdr_layout * layout,const hfs_byte_t * descrs)255 static inline void init_layout(struct hfs_hdr_layout *layout,
256 			       const hfs_byte_t *descrs)
257 {
258 	struct hfs_hdr_descr **base, **p, **q, *tmp;
259 	int lcv, entries = layout->entries;
260 
261 	for (lcv = 0; lcv < entries; ++lcv, descrs += 12) {
262 		layout->order[lcv] = &layout->descr[lcv];
263 		layout->descr[lcv].id     = hfs_get_hl(descrs);
264 		layout->descr[lcv].offset = hfs_get_hl(descrs + 4);
265 		layout->descr[lcv].length = hfs_get_hl(descrs + 8);
266 	}
267 	for (lcv = layout->entries; lcv < HFS_HDR_MAX; ++lcv) {
268 		layout->order[lcv] = NULL;
269 		layout->descr[lcv].id     = 0;
270 		layout->descr[lcv].offset = 0;
271 		layout->descr[lcv].length = 0;
272 	}
273 
274 	/* Sort the 'order' array using an insertion sort */
275 	base = &layout->order[0];
276 	for (p = (base+1); p < (base+entries); ++p) {
277 		q=p;
278 		while ((*q)->offset < (*(q-1))->offset) {
279 			tmp = *q;
280 			*q = *(q-1);
281 			*(--q) = tmp;
282 			if (q == base) break;
283 		}
284 	}
285 }
286 
287 /*
288  * adjust_forks()
289  */
adjust_forks(struct hfs_cat_entry * entry,const struct hfs_hdr_layout * layout)290 static inline void adjust_forks(struct hfs_cat_entry *entry,
291 				const struct hfs_hdr_layout *layout)
292 {
293 	int lcv;
294 
295 	for (lcv = 0; lcv < layout->entries; ++lcv) {
296 		const struct hfs_hdr_descr *descr = &layout->descr[lcv];
297 
298 		if ((descr->id == HFS_HDR_DATA) &&
299 		    (descr->length != entry->u.file.data_fork.lsize)) {
300 			entry->u.file.data_fork.lsize = descr->length;
301 			hfs_extent_adj(&entry->u.file.data_fork);
302 		} else if ((descr->id == HFS_HDR_RSRC) &&
303 			   (descr->length != entry->u.file.rsrc_fork.lsize)) {
304 			entry->u.file.rsrc_fork.lsize = descr->length;
305 			hfs_extent_adj(&entry->u.file.rsrc_fork);
306 		}
307 	}
308 }
309 
310 /*
311  * get_dates()
312  */
get_dates(const struct hfs_cat_entry * entry,const struct inode * inode,hfs_u32 dates[3])313 static void get_dates(const struct hfs_cat_entry *entry,
314 		      const struct inode *inode,  hfs_u32 dates[3])
315 {
316 	dates[0] = hfs_m_to_htime(entry->create_date);
317 	dates[1] = hfs_m_to_htime(entry->modify_date);
318 	dates[2] = hfs_m_to_htime(entry->backup_date);
319 }
320 
321 /*
322  * set_dates()
323  */
set_dates(struct hfs_cat_entry * entry,struct inode * inode,const hfs_u32 * dates)324 static void set_dates(struct hfs_cat_entry *entry, struct inode *inode,
325 		      const hfs_u32 *dates)
326 {
327 	hfs_u32 tmp;
328 
329 	tmp = hfs_h_to_mtime(dates[0]);
330 	if (entry->create_date != tmp) {
331 		entry->create_date = tmp;
332 		hfs_cat_mark_dirty(entry);
333 	}
334 	tmp = hfs_h_to_mtime(dates[1]);
335 	if (entry->modify_date != tmp) {
336 		entry->modify_date = tmp;
337 		inode->i_ctime = inode->i_atime = inode->i_mtime =
338 			hfs_h_to_utime(dates[1]);
339 		hfs_cat_mark_dirty(entry);
340 	}
341 	tmp = hfs_h_to_mtime(dates[2]);
342 	if (entry->backup_date != tmp) {
343 		entry->backup_date = tmp;
344 		hfs_cat_mark_dirty(entry);
345 	}
346 }
347 
hdr_llseek(struct file * file,loff_t offset,int origin)348 loff_t hdr_llseek(struct file *file, loff_t offset, int origin)
349 {
350 	long long retval;
351 
352 	switch (origin) {
353 		case 2:
354 			offset += file->f_dentry->d_inode->i_size;
355 			break;
356 		case 1:
357 			offset += file->f_pos;
358 	}
359 	retval = -EINVAL;
360 	if (offset>=0 && offset<file->f_dentry->d_inode->i_size) {
361 		if (offset != file->f_pos) {
362 			file->f_pos = offset;
363 			file->f_reada = 0;
364 			file->f_version = ++event;
365 		}
366 		retval = offset;
367 	}
368 	return retval;
369 }
370 
371 /*
372  * hdr_read()
373  *
374  * This is the read field in the inode_operations structure for
375  * header files.  The purpose is to transfer up to 'count' bytes
376  * from the file corresponding to 'inode', beginning at
377  * 'filp->offset' bytes into the file.	The data is transferred to
378  * user-space at the address 'buf'.  Returns the number of bytes
379  * successfully transferred.
380  */
381 /* XXX: what about the entry count changing on us? */
hdr_read(struct file * filp,char * buf,hfs_rwarg_t count,loff_t * ppos)382 static hfs_rwret_t hdr_read(struct file * filp, char * buf,
383 			    hfs_rwarg_t count, loff_t *ppos)
384 {
385 	struct inode *inode = filp->f_dentry->d_inode;
386 	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
387 	const struct hfs_hdr_layout *layout;
388 	off_t start, length, offset;
389 	loff_t pos = *ppos;
390 	int left, lcv, read = 0;
391 
392 	if (!S_ISREG(inode->i_mode)) {
393 		hfs_warn("hfs_hdr_read: mode = %07o\n",inode->i_mode);
394 		return -EINVAL;
395 	}
396 
397 	if (HFS_I(inode)->layout) {
398 		layout = HFS_I(inode)->layout;
399 	} else {
400 		layout = HFS_I(inode)->default_layout;
401 	}
402 
403 	/* Adjust count to fit within the bounds of the file */
404 	if (pos != (unsigned)pos || pos >= inode->i_size || count <= 0) {
405 		return 0;
406 	} else if (count > inode->i_size - pos) {
407 		count = inode->i_size - pos;
408 	}
409 
410 	/* Handle the fixed-location portion */
411 	length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 +
412 		 sizeof(hfs_u16) + layout->entries * (3 * sizeof(hfs_u32));
413 	if (pos < length) {
414 		struct hdr_hdr meta;
415 
416 		left = length - pos;
417 		if (left > count) {
418 			left = count;
419 		}
420 
421 		hdr_build_meta(&meta, layout, entry);
422 		left -= copy_to_user(buf, ((char *)&meta) + pos, left);
423 		count -= left;
424 		read += left;
425 		pos += left;
426 		buf += left;
427 	}
428 	if (!count) {
429 		goto done;
430 	}
431 
432 	/* Handle the actual data */
433 	for (lcv = 0; count && (lcv < layout->entries); ++lcv) {
434 		const struct hfs_hdr_descr *descr = layout->order[lcv];
435 		struct hfs_fork *fork;
436 		char tmp[16], *p;
437 		off_t limit;
438 
439 		/* stop reading if we run out of descriptors early */
440 		if (!descr) {
441 			break;
442 		}
443 
444 		/* find start and length of this entry */
445 		start = descr->offset;
446 		length = dlength(descr, entry);
447 
448 		/* Skip to next entry if this one is empty or isn't needed */
449 		if (!length || (pos >= start + length)) {
450 			continue;
451 		}
452 
453 		/* Pad with zeros to the start of this entry if needed */
454 		if (pos < start) {
455 			left = start - pos;
456 			if (left > count) {
457 				left = count;
458 			}
459 			clear_user(buf, left);
460 			count -= left;
461 			read += left;
462 			pos += left;
463 			buf += left;
464 		}
465 		if (!count) {
466 			goto done;
467 		}
468 
469 		/* locate and/or construct the data for this entry */
470 		fork = NULL;
471 		p = NULL;
472 		switch (descr->id) {
473 		case HFS_HDR_DATA:
474 			fork = &entry->u.file.data_fork;
475 			limit = fork->lsize;
476 			break;
477 
478 		case HFS_HDR_RSRC:
479 			fork = &entry->u.file.rsrc_fork;
480 			limit = fork->lsize;
481 			break;
482 
483 		case HFS_HDR_FNAME:
484 			p = entry->key.CName.Name;
485 			limit = entry->key.CName.Len;
486 			break;
487 
488 		case HFS_HDR_OLDI:
489 		case HFS_HDR_DATES:
490 			get_dates(entry, inode, (hfs_u32 *)tmp);
491 			if (descr->id == HFS_HDR_DATES) {
492 				/* XXX: access date. hfsplus actually
493                                    has this. */
494 				memcpy(tmp + 12, tmp + 4, 4);
495 			} else if ((entry->type == HFS_CDR_FIL) &&
496 				   (entry->u.file.flags & HFS_FIL_LOCK)) {
497 				hfs_put_hl(HFS_AFP_RDONLY, tmp + 12);
498 			} else {
499 				hfs_put_nl(0, tmp + 12);
500 			}
501 			p = tmp;
502 			limit = 16;
503 			break;
504 
505 		case HFS_HDR_FINFO:
506 			p = (char *)&entry->info;
507 			limit = 32;
508 			break;
509 
510 		case HFS_HDR_AFPI:
511 			/* XXX: this needs to do more mac->afp mappings */
512 			hfs_put_ns(0, tmp);
513 			if ((entry->type == HFS_CDR_FIL) &&
514 			    (entry->u.file.flags & HFS_FIL_LOCK)) {
515 				hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
516 			} else {
517 				hfs_put_ns(0, tmp + 2);
518 			}
519 			p = tmp;
520 			limit = 4;
521 		        break;
522 
523 		case HFS_HDR_PRODOSI:
524 			/* XXX: this needs to do mac->prodos translations */
525 			memset(tmp, 0, 8);
526 #if 0
527 			hfs_put_ns(0, tmp); /* access */
528 			hfs_put_ns(0, tmp); /* type */
529 			hfs_put_nl(0, tmp); /* aux type */
530 #endif
531 			p = tmp;
532 			limit = 8;
533 		        break;
534 
535 		case HFS_HDR_MACI:
536 			hfs_put_ns(0, tmp);
537 			if (entry->type == HFS_CDR_FIL) {
538 				hfs_put_hs(entry->u.file.flags, tmp + 2);
539 			} else {
540 				hfs_put_ns(entry->u.dir.flags, tmp + 2);
541 			}
542 			p = tmp;
543 			limit = 4;
544 			break;
545 
546 		case HFS_HDR_DID:
547 		        /* if it's rootinfo, stick the next available did in
548 			 * the did slot. */
549 			limit = 4;
550 			if (entry->cnid == htonl(HFS_ROOT_CNID)) {
551 				struct hfs_mdb *mdb = entry->mdb;
552 				const struct hfs_name *reserved =
553 				HFS_SB(mdb->sys_mdb)->s_reserved2;
554 
555 				while (reserved->Len) {
556 					if (hfs_streq(reserved->Name,
557 						      reserved->Len,
558 						      entry->key.CName.Name,
559 						      entry->key.CName.Len)) {
560 						hfs_put_hl(mdb->next_id, tmp);
561 						p = tmp;
562 						goto hfs_did_done;
563 					}
564 					reserved++;
565 				}
566 			}
567 			p = (char *) &entry->cnid;
568 hfs_did_done:
569 			break;
570 
571 		case HFS_HDR_SNAME:
572 		default:
573 			limit = 0;
574 		}
575 
576 		/* limit the transfer to the available data
577 		   of to the stated length of the entry. */
578 		if (length > limit) {
579 			length = limit;
580 		}
581 		offset = pos - start;
582 		left = length - offset;
583 		if (left > count) {
584 			left = count;
585 		}
586 		if (left <= 0) {
587 			continue;
588 		}
589 
590 		/* transfer the data */
591 		if (p) {
592 			left -= copy_to_user(buf, p + offset, left);
593 		} else if (fork) {
594 			left = hfs_do_read(inode, fork, offset, buf, left,
595 					   filp->f_reada != 0);
596 			if (left > 0) {
597 				filp->f_reada = 1;
598 			} else if (!read) {
599 				return left;
600 			} else {
601 				goto done;
602 			}
603 		}
604 		count -= left;
605 		read += left;
606 		pos += left;
607 		buf += left;
608 	}
609 
610 	/* Pad the file out with zeros */
611 	if (count) {
612 		clear_user(buf, count);
613 		read += count;
614 		pos += count;
615 	}
616 
617 done:
618 	if (read) {
619 		inode->i_atime = CURRENT_TIME;
620 		*ppos = pos;
621 		mark_inode_dirty(inode);
622 	}
623 	return read;
624 }
625 
626 /*
627  * hdr_write()
628  *
629  * This is the write() entry in the file_operations structure for
630  * header files.  The purpose is to transfer up to 'count' bytes
631  * to the file corresponding to 'inode' beginning at offset
632  * '*ppos' from user-space at the address 'buf'.
633  * The return value is the number of bytes actually transferred.
634  */
hdr_write(struct file * filp,const char * buf,hfs_rwarg_t count,loff_t * ppos)635 static hfs_rwret_t hdr_write(struct file *filp, const char *buf,
636 			     hfs_rwarg_t count, loff_t *ppos)
637 {
638 	struct inode *inode = filp->f_dentry->d_inode;
639         struct hfs_cat_entry *entry = HFS_I(inode)->entry;
640         struct hfs_hdr_layout *layout;
641         off_t start, length, offset;
642         int left, lcv, written = 0;
643 	struct hdr_hdr meta;
644 	int built_meta = 0;
645         loff_t pos;
646 
647 	if (!S_ISREG(inode->i_mode)) {
648 		hfs_warn("hfs_hdr_write: mode = %07o\n", inode->i_mode);
649 		return -EINVAL;
650 	}
651 
652 	pos = (filp->f_flags & O_APPEND) ? inode->i_size : *ppos;
653 
654 	if (count <= 0 || pos != (unsigned)pos) {
655 		return 0;
656 	}
657 
658 	if (!HFS_I(inode)->layout) {
659 		HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);
660 	}
661 	layout = HFS_I(inode)->layout;
662 
663 	/* Handle the 'magic', 'version', 'filler' and 'entries' fields */
664 	length = sizeof(hfs_u32) + sizeof(hfs_u32) + 16 + sizeof(hfs_u16);
665 	if (pos < length) {
666 		hdr_build_meta(&meta, layout, entry);
667 		built_meta = 1;
668 
669 		left = length - pos;
670 		if (left > count) {
671 			left = count;
672 		}
673 
674 		left -= copy_from_user(((char *)&meta) + pos, buf, left);
675 		layout->magic   = hfs_get_nl(meta.magic);
676 		layout->version = hfs_get_nl(meta.version);
677 		layout->entries = hfs_get_hs(meta.entries);
678 		if (layout->entries > HFS_HDR_MAX) {
679 			/* XXX: should allocate slots dynamically */
680 			hfs_warn("hfs_hdr_write: TRUNCATING TO %d "
681 				 "DESCRIPTORS\n", HFS_HDR_MAX);
682 			layout->entries = HFS_HDR_MAX;
683 		}
684 
685 		count -= left;
686 		written += left;
687 		pos += left;
688 		buf += left;
689 	}
690 	if (!count) {
691 		goto done;
692 	}
693 
694 	/* We know for certain how many entries we have, so process them */
695 	length += layout->entries * 3 * sizeof(hfs_u32);
696 	if (pos < length) {
697 		if (!built_meta) {
698 			hdr_build_meta(&meta, layout, entry);
699 		}
700 
701 		left = length - pos;
702 		if (left > count) {
703 			left = count;
704 		}
705 
706 		left -= copy_from_user(((char *)&meta) + pos, buf, left);
707 		init_layout(layout, meta.descrs);
708 
709 		count -= left;
710 		written += left;
711 		pos += left;
712 		buf += left;
713 
714 		/* Handle possible size changes for the forks */
715 		if (entry->type == HFS_CDR_FIL) {
716 			adjust_forks(entry, layout);
717 			hfs_cat_mark_dirty(entry);
718 		}
719 	}
720 
721 	/* Handle the actual data */
722 	for (lcv = 0; count && (lcv < layout->entries); ++lcv) {
723 		struct hfs_hdr_descr *descr = layout->order[lcv];
724 		struct hfs_fork *fork;
725 		char tmp[16], *p;
726 		off_t limit;
727 
728 		/* stop writing if we run out of descriptors early */
729 		if (!descr) {
730 			break;
731 		}
732 
733 		/* find start and length of this entry */
734 		start = descr->offset;
735 		if ((descr->id == HFS_HDR_DATA) ||
736 		    (descr->id == HFS_HDR_RSRC)) {
737 			if (entry->type == HFS_CDR_FIL) {
738 				length = 0x7fffffff - start;
739 			} else {
740 				continue;
741 			}
742 		} else {
743 			length = dlength(descr, entry);
744 		}
745 
746 		/* Trim length to avoid overlap with the next entry */
747 		if (layout->order[lcv+1] &&
748 		    ((start + length) > layout->order[lcv+1]->offset)) {
749 			length = layout->order[lcv+1]->offset - start;
750 		}
751 
752 		/* Skip to next entry if this one is empty or isn't needed */
753 		if (!length || (pos >= start + length)) {
754 			continue;
755 		}
756 
757 		/* Skip any padding that may exist between entries */
758 		if (pos < start) {
759 			left = start - pos;
760 			if (left > count) {
761 				left = count;
762 			}
763 			count -= left;
764 			written += left;
765 			pos += left;
766 			buf += left;
767 		}
768 		if (!count) {
769 			goto done;
770 		}
771 
772 		/* locate and/or construct the data for this entry */
773 		fork = NULL;
774 		p = NULL;
775 		switch (descr->id) {
776 		case HFS_HDR_DATA:
777 #if 0
778 /* Can't yet write to the data fork via a header file, since there is the
779  * possibility to write via the data file, and the only locking is at the
780  * inode level.
781  */
782 			fork = &entry->u.file.data_fork;
783 			limit = length;
784 #else
785 			limit = 0;
786 #endif
787 			break;
788 
789 		case HFS_HDR_RSRC:
790 			fork = &entry->u.file.rsrc_fork;
791 			limit = length;
792 			break;
793 
794 		case HFS_HDR_OLDI:
795 		case HFS_HDR_DATES:
796 			get_dates(entry, inode, (hfs_u32 *)tmp);
797 			if (descr->id == HFS_HDR_DATES) {
798 				memcpy(tmp + 12, tmp + 4, 4);
799 			} else if ((entry->type == HFS_CDR_FIL) &&
800 				   (entry->u.file.flags & HFS_FIL_LOCK)) {
801 				hfs_put_hl(HFS_AFP_RDONLY, tmp + 12);
802 			} else {
803 				hfs_put_nl(0, tmp + 12);
804 			}
805 			p = tmp;
806 			limit = 16;
807 			break;
808 
809 		case HFS_HDR_FINFO:
810 			p = (char *)&entry->info;
811 			limit = 32;
812 			break;
813 
814 		case HFS_HDR_AFPI:
815 			hfs_put_ns(0, tmp);
816 			if ((entry->type == HFS_CDR_FIL) &&
817 			    (entry->u.file.flags & HFS_FIL_LOCK)) {
818 				hfs_put_hs(HFS_AFP_RDONLY, tmp + 2);
819 			} else {
820 				hfs_put_ns(0, tmp + 2);
821 			}
822 			p = tmp;
823 			limit = 4;
824 			break;
825 
826 		case HFS_HDR_PRODOSI:
827 			/* XXX: this needs to do mac->prodos translations */
828 			memset(tmp, 0, 8);
829 #if 0
830 			hfs_put_ns(0, tmp); /* access */
831 			hfs_put_ns(0, tmp); /* type */
832 			hfs_put_nl(0, tmp); /* aux type */
833 #endif
834 			p = tmp;
835 			limit = 8;
836 		        break;
837 
838 		case HFS_HDR_MACI:
839 			hfs_put_ns(0, tmp);
840 			if (entry->type == HFS_CDR_FIL) {
841 				hfs_put_hs(entry->u.file.flags, tmp + 2);
842 			} else {
843 				hfs_put_ns(entry->u.dir.flags, tmp + 2);
844 			}
845 			p = tmp;
846 			limit = 4;
847 			break;
848 
849 		case HFS_HDR_FNAME:	/* Can't rename a file this way */
850 		case HFS_HDR_DID:       /* can't specify a did this way */
851 		default:
852 			limit = 0;
853 		}
854 
855 		/* limit the transfer to the available data
856 		   of to the stated length of the entry. */
857 		if (length > limit) {
858 			length = limit;
859 		}
860 		offset = pos - start;
861 		left = length - offset;
862 		if (left > count) {
863 			left = count;
864 		}
865 		if (left <= 0) {
866 			continue;
867 		}
868 
869 		/* transfer the data from user space */
870 		if (p) {
871 			left -= copy_from_user(p + offset, buf, left);
872 		} else if (fork) {
873 			left = hfs_do_write(inode, fork, offset, buf, left);
874 		}
875 
876 		/* process the data */
877 		switch (descr->id) {
878 		case HFS_HDR_OLDI:
879 			set_dates(entry, inode, (hfs_u32 *)tmp);
880 			if (entry->type == HFS_CDR_FIL) {
881 				hfs_u8 new_flags = entry->u.file.flags;
882 
883 				if (hfs_get_nl(tmp+12) & htonl(HFS_AFP_WRI)) {
884 					new_flags |= HFS_FIL_LOCK;
885 				} else {
886 					new_flags &= ~HFS_FIL_LOCK;
887 				}
888 
889 				if (new_flags != entry->u.file.flags) {
890 					entry->u.file.flags = new_flags;
891 					hfs_cat_mark_dirty(entry);
892 					hfs_file_fix_mode(entry);
893 				}
894 			}
895 			break;
896 
897 		case HFS_HDR_DATES:
898 			set_dates(entry, inode, (hfs_u32 *)tmp);
899 			break;
900 
901 		case HFS_HDR_FINFO:
902 			hfs_cat_mark_dirty(entry);
903 			break;
904 
905 		case HFS_HDR_MACI:
906 			if (entry->type == HFS_CDR_DIR) {
907 				hfs_u16 new_flags = hfs_get_ns(tmp + 2);
908 
909 				if (entry->u.dir.flags != new_flags) {
910 					entry->u.dir.flags = new_flags;
911 					hfs_cat_mark_dirty(entry);
912 				}
913 			} else {
914 				hfs_u8 new_flags = tmp[3];
915 				hfs_u8 changed = entry->u.file.flags^new_flags;
916 
917 				if (changed) {
918 					entry->u.file.flags = new_flags;
919 					hfs_cat_mark_dirty(entry);
920 					if (changed & HFS_FIL_LOCK) {
921 						hfs_file_fix_mode(entry);
922 					}
923 				}
924 			}
925 			break;
926 
927 		case HFS_HDR_DATA:
928 		case HFS_HDR_RSRC:
929 			if (left <= 0) {
930 				if (!written) {
931 					return left;
932 				} else {
933 					goto done;
934 				}
935 			} else if (fork->lsize > descr->length) {
936 				descr->length = fork->lsize;
937 			}
938 			break;
939 
940 		case HFS_HDR_FNAME:	/* Can't rename a file this way */
941 		case HFS_HDR_DID:       /* Can't specify a did this way */
942 		case HFS_HDR_PRODOSI:   /* not implemented yet */
943 		case HFS_HDR_AFPI:      /* ditto */
944 		default:
945 			break;
946 		}
947 
948 		count -= left;
949 		written += left;
950 		pos += left;
951 		buf += left;
952 	}
953 
954 	/* Skip any padding at the end */
955 	if (count) {
956 		written += count;
957 		pos += count;
958 	}
959 
960 done:
961 	*ppos = pos;
962 	if (written > 0) {
963 	        if (pos > inode->i_size)
964 		        inode->i_size = pos;
965 	        inode->i_mtime = inode->i_atime = CURRENT_TIME;
966 		mark_inode_dirty(inode);
967 	}
968 	return written;
969 }
970 
971 /*
972  * hdr_truncate()
973  *
974  * This is the truncate field in the inode_operations structure for
975  * header files.  The purpose is to allocate or release blocks as needed
976  * to satisfy a change in file length.
977  */
hdr_truncate(struct inode * inode,size_t size)978 void hdr_truncate(struct inode *inode, size_t size)
979 {
980 	struct hfs_cat_entry *entry = HFS_I(inode)->entry;
981 	struct hfs_hdr_layout *layout;
982 	int lcv, last;
983 
984 	inode->i_size = size;
985 	if (!HFS_I(inode)->layout) {
986 		HFS_I(inode)->layout = dup_layout(HFS_I(inode)->default_layout);
987 	}
988 	layout = HFS_I(inode)->layout;
989 
990 	last = layout->entries - 1;
991 	for (lcv = 0; lcv <= last; ++lcv) {
992 		struct hfs_hdr_descr *descr = layout->order[lcv];
993 		struct hfs_fork *fork;
994 		hfs_u32 offset;
995 
996 		if (!descr) {
997 			break;
998 		}
999 
1000 		if (descr->id == HFS_HDR_RSRC) {
1001 			fork = &entry->u.file.rsrc_fork;
1002 #if 0
1003 /* Can't yet truncate the data fork via a header file, since there is the
1004  * possibility to truncate via the data file, and the only locking is at
1005  * the inode level.
1006  */
1007 		} else if (descr->id == HFS_HDR_DATA) {
1008 			fork = &entry->u.file.data_fork;
1009 #endif
1010 		} else {
1011 			continue;
1012 		}
1013 
1014 		offset = descr->offset;
1015 
1016 		if ((lcv != last) && ((offset + descr->length) <= size)) {
1017 			continue;
1018 		}
1019 
1020 		if (offset < size) {
1021 			descr->length = size - offset;
1022 		} else {
1023 			descr->length = 0;
1024 		}
1025 		if (fork->lsize != descr->length) {
1026 			fork->lsize = descr->length;
1027 			hfs_extent_adj(fork);
1028 			hfs_cat_mark_dirty(entry);
1029 		}
1030 	}
1031 }
1032