4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Rock Ridge extensions to the System Use Sharing protocol
28 * for the High Sierra filesystem
31 #include <sys/types.h>
32 #include <sys/t_lock.h>
33 #include <sys/param.h>
34 #include <sys/systm.h>
36 #include <sys/signal.h>
41 #include <sys/pathname.h>
43 #include <sys/vnode.h>
49 #include <sys/mkdev.h>
54 #include <sys/fs/hsfs_spec.h>
55 #include <sys/fs/hsfs_isospec.h>
56 #include <sys/fs/hsfs_node.h>
57 #include <sys/fs/hsfs_impl.h>
58 #include <sys/fs/hsfs_susp.h>
59 #include <sys/fs/hsfs_rrip.h>
61 #include <sys/statvfs.h>
62 #include <sys/mount.h>
64 #include <sys/errno.h>
65 #include <sys/debug.h>
66 #include "sys/fs_subr.h"
67 #include <sys/cmn_err.h>
69 static void form_time(int, uchar_t
*, struct timeval
*);
70 static void name_parse(int, uchar_t
*, size_t, uchar_t
*, int *,
74 * Signature table for RRIP
76 ext_signature_t rrip_signature_table
[ ] = {
77 RRIP_CL
, rrip_child_link
,
79 RRIP_PL
, rrip_parent_link
,
80 RRIP_PN
, rrip_dev_nodes
,
81 RRIP_PX
, rrip_file_attr
,
82 RRIP_RE
, rrip_reloc_dir
,
83 RRIP_RR
, rrip_rock_ridge
,
84 RRIP_SL
, rrip_sym_link
,
85 RRIP_TF
, rrip_file_time
,
93 * sig_handler() for RRIP signature "PN"
95 * This function parses out the major and minor numbers from the "PN
99 rrip_dev_nodes(sig_args_t
*sig_args_p
)
101 uchar_t
*pn_ptr
= sig_args_p
->SUF_ptr
;
102 major_t major_dev
= (major_t
)RRIP_MAJOR(pn_ptr
);
103 minor_t minor_dev
= (minor_t
)RRIP_MINOR(pn_ptr
);
105 sig_args_p
->hdp
->r_dev
= makedevice(major_dev
, minor_dev
);
107 return (pn_ptr
+ SUF_LEN(pn_ptr
));
113 * sig_handler() for RRIP signature "PX"
115 * This function parses out the file attributes of a file from the "PX"
116 * SUF. The attributes is finds are : st_mode, st_nlink, st_uid,
120 rrip_file_attr(sig_args_t
*sig_args_p
)
122 uchar_t
*px_ptr
= sig_args_p
->SUF_ptr
;
123 struct hs_direntry
*hdp
= sig_args_p
->hdp
;
125 hdp
->mode
= RRIP_MODE(px_ptr
);
126 hdp
->nlink
= RRIP_NLINK(px_ptr
);
127 hdp
->uid
= RRIP_UID(px_ptr
);
128 hdp
->gid
= RRIP_GID(px_ptr
);
130 if (SUF_LEN(px_ptr
) >= RRIP_PX_SIZE
)
131 hdp
->inode
= (ino64_t
)RRIP_INO(px_ptr
);
135 hdp
->type
= IFTOVT(hdp
->mode
);
137 return (px_ptr
+ SUF_LEN(px_ptr
));
143 * support function for rrip_file_time()
145 * This function decides whether to parse the times in a long time form
146 * (17 bytes) or a short time form (7 bytes). These time formats are
147 * defined in the ISO 9660 specification.
150 form_time(int time_length
, uchar_t
*file_time
, struct timeval
*tvp
)
152 if (time_length
== ISO_DATE_LEN
)
153 hs_parse_longdate(file_time
, tvp
);
155 hs_parse_dirdate(file_time
, tvp
);
162 * sig_handler() for RRIP signature RRIP_TF
164 * This function parses out the file time attributes of a file from the
165 * "TI" SUF. The times it parses are : st_mtime, st_atime and st_ctime.
167 * The function form_time is a support function only used in this
171 rrip_file_time(sig_args_t
*sig_args_p
)
173 uchar_t
*tf_ptr
= sig_args_p
->SUF_ptr
;
175 if (IS_TIME_BIT_SET(RRIP_TF_FLAGS(tf_ptr
), RRIP_TF_ACCESS_BIT
)) {
176 form_time(RRIP_TF_TIME_LENGTH(tf_ptr
),
177 RRIP_tf_access(tf_ptr
),
178 &sig_args_p
->hdp
->adate
);
181 if (IS_TIME_BIT_SET(RRIP_TF_FLAGS(tf_ptr
), RRIP_TF_MODIFY_BIT
)) {
182 form_time(RRIP_TF_TIME_LENGTH(tf_ptr
), RRIP_tf_modify(tf_ptr
),
183 &sig_args_p
->hdp
->mdate
);
186 if (IS_TIME_BIT_SET(RRIP_TF_FLAGS(tf_ptr
), RRIP_TF_ATTRIBUTES_BIT
)) {
187 form_time(RRIP_TF_TIME_LENGTH(tf_ptr
),
188 RRIP_tf_attributes(tf_ptr
),
189 &sig_args_p
->hdp
->cdate
);
192 return (tf_ptr
+ SUF_LEN(tf_ptr
));
200 * This is a generic fuction used for sym links and filenames. The
201 * flags passed to it effect the way the name/component field is parsed.
203 * The return value will be the NAME_CONTINUE or NAME_CHANGE value.
208 int rrip_flags
, /* component/name flag */
209 uchar_t
*SUA_string
, /* string from SUA */
210 size_t SUA_string_len
, /* length of SUA string */
211 uchar_t
*dst
, /* string to copy to */
212 int *dst_lenp
, /* ptr to cur. str len */
213 ulong_t
*name_flags_p
, /* internal name flags */
214 int dst_size
) /* limit dest string to this value */
219 if (IS_NAME_BIT_SET(rrip_flags
, RRIP_NAME_ROOT
))
222 if (IS_NAME_BIT_SET(rrip_flags
, RRIP_NAME_CURRENT
)) {
223 SUA_string
= (uchar_t
*)".";
227 if (IS_NAME_BIT_SET(rrip_flags
, RRIP_NAME_PARENT
)) {
228 SUA_string
= (uchar_t
*)"..";
234 * For now, ignore the following flags and return.
235 * have to figure out how to get host name in kernel.
236 * Unsure if this even should be done.
238 if (IS_NAME_BIT_SET(rrip_flags
, RRIP_NAME_VOLROOT
) ||
239 IS_NAME_BIT_SET(rrip_flags
, RRIP_NAME_HOST
)) {
241 "VOLUME ROOT and NAME_HOST currently unsupported\n");
246 * strlcat() has two nice properties:
247 * - the size of the output buffer includes the trailing '\0'
248 * - we pass "total size" not "remaining size"
249 * It'd be the ideal candidate for this codeblock - make it:
251 * strlcat(dst, SUA_string,
252 * MIN(dstsize, strlen(dst) + SUA_string_len + 1));
254 * Unfortunately, strlcat() cannot deal with input strings
255 * that are not NULL-terminated - like SUA_string can be in
256 * our case here. So we can't use it :(
257 * Now strncat() doesn't work either - because it doesn't deal
258 * with strings for which the 'potential NULL-termination' isn't
259 * accessible - strncat(dst, NULL, 0) crashes although it copies
260 * nothing in any case. If the SUA ends on a mapping boundary,
261 * then telling strncat() to copy no more than the remaining bytes
262 * in the buffer is of no avail if there's no NULL byte in them.
264 * Hence - binary copy. What are all these str* funcs for ??
266 dst_size
--; /* trailing '\0' */
268 off
= strlen((char *)dst
);
269 len
= MIN(dst_size
- off
, SUA_string_len
);
270 bcopy((char *)SUA_string
, (char *)(dst
+ off
), len
);
271 dst
[off
+ len
] = '\0';
272 *dst_lenp
= strlen((char *)dst
);
274 if (IS_NAME_BIT_SET(rrip_flags
, RRIP_NAME_CONTINUE
))
275 SET_NAME_BIT(*(name_flags_p
), RRIP_NAME_CONTINUE
);
277 SET_NAME_BIT(*(name_flags_p
), RRIP_NAME_CHANGE
);
284 * sig_handler() for RRIP signature RRIP_NM
286 * This function handles the name of the current file. It is case
287 * sensitive to whatever was put into the field and does NO
288 * translation. It will take whatever characters were in the field.
290 * Because the flags effect the way the name is parsed the same way
291 * that the sym_link component parsing is done, we will use the same
292 * function to do the actual parsing.
295 rrip_name(sig_args_t
*sig_args_p
)
297 uchar_t
*nm_ptr
= sig_args_p
->SUF_ptr
;
299 if ((sig_args_p
->name_p
== NULL
) ||
300 (sig_args_p
->name_len_p
== NULL
))
303 * If we have a "." or ".." directory, we should not look for
306 if (HDE_NAME_LEN(sig_args_p
->dirp
) == 1) {
307 if (*((char *)HDE_name(sig_args_p
->dirp
)) == '\0') {
308 (void) strcpy((char *)sig_args_p
->name_p
, ".");
309 *sig_args_p
->name_len_p
= 1;
311 } else if (*((char *)HDE_name(sig_args_p
->dirp
)) == '\1') {
312 (void) strcpy((char *)sig_args_p
->name_p
, "..");
313 *sig_args_p
->name_len_p
= 2;
318 name_parse((int)RRIP_NAME_FLAGS(nm_ptr
), RRIP_name(nm_ptr
),
319 (size_t)RRIP_NAME_LEN(nm_ptr
), sig_args_p
->name_p
,
320 sig_args_p
->name_len_p
, &(sig_args_p
->name_flags
),
324 return (nm_ptr
+ SUF_LEN(nm_ptr
));
331 * sig_handler() for RRIP signature RRIP_SL
333 * creates a symlink buffer to simulate sym_links.
336 rrip_sym_link(sig_args_t
*sig_args_p
)
338 uchar_t
*sl_ptr
= sig_args_p
->SUF_ptr
;
341 struct hs_direntry
*hdp
= sig_args_p
->hdp
;
345 if (hdp
->type
!= VLNK
)
349 * If the sym link has already been created, don't recreate it
351 if (IS_NAME_BIT_SET(sig_args_p
->name_flags
, RRIP_SYM_LINK_COMPLETE
))
354 sym_link
= kmem_alloc(MAXPATHLEN
+ 1, KM_SLEEP
);
357 * If there is an original string put it into sym_link[], otherwise
358 * initialize sym_link[] to the empty string.
360 if (hdp
->sym_link
!= NULL
) {
361 sym_link_len
= (int)strlen(strcpy(sym_link
, hdp
->sym_link
));
367 /* for all components */
368 for (comp_ptr
= RRIP_sl_comp(sl_ptr
);
369 comp_ptr
< (sl_ptr
+ SUF_LEN(sl_ptr
));
370 comp_ptr
+= RRIP_COMP_LEN(comp_ptr
)) {
372 name_parse((int)RRIP_COMP_FLAGS(comp_ptr
),
374 (size_t)RRIP_COMP_NAME_LEN(comp_ptr
), (uchar_t
*)sym_link
,
375 &sym_link_len
, &(sig_args_p
->name_flags
),
379 * If the component is continued don't put a '/' in
380 * the pathname, but do NULL terminate it.
382 if (IS_NAME_BIT_SET(RRIP_COMP_FLAGS(comp_ptr
),
383 RRIP_NAME_CONTINUE
)) {
384 sym_link
[sym_link_len
] = '\0';
386 sym_link
[sym_link_len
] = '/';
387 sym_link
[sym_link_len
+ 1] = '\0';
389 /* add 1 to sym_link_len for '/' */
396 * If we reached the end of the symbolic link, take out the
397 * last slash, but don't change ROOT "/" to an empty string.
399 if (!IS_NAME_BIT_SET(RRIP_SL_FLAGS(sl_ptr
), RRIP_NAME_CONTINUE
) &&
400 sym_link_len
> 1 && sym_link
[sym_link_len
- 1] == '/')
401 sym_link
[--sym_link_len
] = '\0';
404 * if no memory has been allocated, get some, otherwise, append
405 * to the current allocation
408 tmp_sym_link
= kmem_alloc(SYM_LINK_LEN(sym_link
), KM_SLEEP
);
410 (void) strcpy(tmp_sym_link
, sym_link
);
412 if (hdp
->sym_link
!= NULL
)
413 kmem_free(hdp
->sym_link
, (size_t)(hdp
->ext_size
+ 1));
415 hdp
->sym_link
= (char *)&tmp_sym_link
[0];
416 /* the size of a symlink is its length */
417 hdp
->ext_size
= (uint_t
)strlen(tmp_sym_link
);
419 if (!IS_NAME_BIT_SET(RRIP_SL_FLAGS(sl_ptr
), RRIP_NAME_CONTINUE
)) {
420 /* reached the end of the symbolic link */
421 SET_NAME_BIT(sig_args_p
->name_flags
, RRIP_SYM_LINK_COMPLETE
);
424 kmem_free(sym_link
, MAXPATHLEN
+ 1);
426 return (sl_ptr
+ SUF_LEN(sl_ptr
));
432 * This function will copy the rrip name to the "to" buffer, if it
435 * XXX - We should speed this up by implementing the search in
436 * parse_sua(). It works right now, so I don't want to mess with it.
440 char *from
, /* name to copy */
441 char *to
, /* string to copy "from" to */
442 char *tmp_name
, /* temp storage for original name */
443 uchar_t
*dirp
, /* directory entry pointer */
444 uint_t last_offset
, /* last index into current dir block */
445 struct hsfs
*fsp
, /* filesystem pointer */
446 struct hs_direntry
*hdp
) /* destination directory entry ptr */
452 if ((to
== NULL
) || (from
== NULL
) || (dirp
== NULL
))
455 /* special handling for '.' and '..' */
457 if (HDE_NAME_LEN(dirp
) == 1) {
458 if (*((char *)HDE_name(dirp
)) == '\0') {
459 (void) strcpy(to
, ".");
461 } else if (*((char *)HDE_name(dirp
)) == '\1') {
462 (void) strcpy(to
, "..");
468 ret_val
= parse_sua((uchar_t
*)to
, &size
, &change_flag
,
469 dirp
, last_offset
, hdp
, fsp
, NULL
, 0);
471 if (IS_NAME_BIT_SET(change_flag
, RRIP_NAME_CHANGE
) && !ret_val
)
475 * Well, the name was not found
477 * make rripname an upper case "nm" (to), so that
478 * we can compare it the current HDE_DIR_NAME()
479 * without nuking the original "nm", for future case
480 * sensitive name comparing
482 (void) strcpy(tmp_name
, from
); /* keep original */
483 size
= hs_uppercase_copy(tmp_name
, from
, (int)strlen(from
));
493 * This function is fairly bogus. All it does is cause a failure of
494 * the hs_parsedir, so that no vnode will be made for it and
495 * essentially, the directory will no longer be seen. This is part
496 * of the directory hierarchy mess, where the relocated directory will
497 * be hidden as far as ISO 9660 is concerned. When we hit the child
498 * link "CL" SUF, then we will read the new directory.
501 rrip_reloc_dir(sig_args_t
*sig_args_p
)
503 uchar_t
*re_ptr
= sig_args_p
->SUF_ptr
;
505 sig_args_p
->flags
= RELOC_DIR
;
507 return (re_ptr
+ SUF_LEN(re_ptr
));
515 * This is the child link part of the directory hierarchy stuff and
516 * this does not really do much anyway. All it does is read the
517 * directory entry that the child link SUF contains. All should be
521 rrip_child_link(sig_args_t
*sig_args_p
)
523 uchar_t
*cl_ptr
= sig_args_p
->SUF_ptr
;
525 sig_args_p
->hdp
->ext_lbn
= RRIP_CHILD_LBN(cl_ptr
);
527 hs_filldirent(sig_args_p
->fsp
->hsfs_rootvp
, sig_args_p
->hdp
);
529 sig_args_p
->flags
= 0;
531 return (cl_ptr
+ SUF_LEN(cl_ptr
));
538 * This is the parent link part of the directory hierarchy stuff and
539 * this does not really do much anyway. All it does is read the
540 * directory entry that the parent link SUF contains. All should be
544 rrip_parent_link(sig_args_t
*sig_args_p
)
546 uchar_t
*pl_ptr
= sig_args_p
->SUF_ptr
;
548 sig_args_p
->hdp
->ext_lbn
= RRIP_PARENT_LBN(pl_ptr
);
550 hs_filldirent(sig_args_p
->fsp
->hsfs_rootvp
, sig_args_p
->hdp
);
552 sig_args_p
->flags
= 0;
554 return (pl_ptr
+ SUF_LEN(pl_ptr
));
561 * This function is supposed to aid in speed of the filesystem.
563 * XXX - It is only here as a place holder so far.
566 rrip_rock_ridge(sig_args_t
*sig_args_p
)
568 uchar_t
*rr_ptr
= sig_args_p
->SUF_ptr
;
570 return (rr_ptr
+ SUF_LEN(rr_ptr
));