1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * Rock Ridge extensions to the System Use Sharing protocol 31 * for the High Sierra filesystem 32 */ 33 34 #include <sys/types.h> 35 #include <sys/t_lock.h> 36 #include <sys/param.h> 37 #include <sys/systm.h> 38 #include <sys/kmem.h> 39 #include <sys/signal.h> 40 #include <sys/user.h> 41 #include <sys/proc.h> 42 #include <sys/disp.h> 43 #include <sys/buf.h> 44 #include <sys/pathname.h> 45 #include <sys/vfs.h> 46 #include <sys/vnode.h> 47 #include <sys/file.h> 48 #include <sys/uio.h> 49 #include <sys/conf.h> 50 #include <sys/stat.h> 51 #include <sys/mode.h> 52 #include <sys/mkdev.h> 53 #include <sys/ddi.h> 54 #include <sys/sunddi.h> 55 56 #include <vm/page.h> 57 58 #include <sys/fs/hsfs_spec.h> 59 #include <sys/fs/hsfs_isospec.h> 60 #include <sys/fs/hsfs_node.h> 61 #include <sys/fs/hsfs_impl.h> 62 #include <sys/fs/hsfs_susp.h> 63 #include <sys/fs/hsfs_rrip.h> 64 65 #include <sys/statvfs.h> 66 #include <sys/mount.h> 67 #include <sys/swap.h> 68 #include <sys/errno.h> 69 #include <sys/debug.h> 70 #include "fs/fs_subr.h" 71 #include <sys/cmn_err.h> 72 73 static void form_time(int, uchar_t *, struct timeval *); 74 static void name_parse(int, uchar_t *, size_t, uchar_t *, int *, 75 ulong_t *, int); 76 77 /* 78 * Signature table for RRIP 79 */ 80 ext_signature_t rrip_signature_table[ ] = { 81 RRIP_CL, rrip_child_link, 82 RRIP_NM, rrip_name, 83 RRIP_PL, rrip_parent_link, 84 RRIP_PN, rrip_dev_nodes, 85 RRIP_PX, rrip_file_attr, 86 RRIP_RE, rrip_reloc_dir, 87 RRIP_RR, rrip_rock_ridge, 88 RRIP_SL, rrip_sym_link, 89 RRIP_TF, rrip_file_time, 90 (char *)NULL, NULL 91 }; 92 93 94 /* 95 * rrip_dev_nodes() 96 * 97 * sig_handler() for RRIP signature "PN" 98 * 99 * This function parses out the major and minor numbers from the "PN 100 * " SUF. 101 */ 102 uchar_t * 103 rrip_dev_nodes(sig_args_t *sig_args_p) 104 { 105 uchar_t *pn_ptr = sig_args_p->SUF_ptr; 106 major_t major_dev = (major_t)RRIP_MAJOR(pn_ptr); 107 minor_t minor_dev = (minor_t)RRIP_MINOR(pn_ptr); 108 109 sig_args_p->hdp->r_dev = makedevice(major_dev, minor_dev); 110 111 return (pn_ptr + SUF_LEN(pn_ptr)); 112 } 113 114 /* 115 * rrip_file_attr() 116 * 117 * sig_handler() for RRIP signature "PX" 118 * 119 * This function parses out the file attributes of a file from the "PX" 120 * SUF. The attributes is finds are : st_mode, st_nlink, st_uid, 121 * and st_gid. 122 */ 123 uchar_t * 124 rrip_file_attr(sig_args_t *sig_args_p) 125 { 126 uchar_t *px_ptr = sig_args_p->SUF_ptr; 127 struct hs_direntry *hdp = sig_args_p->hdp; 128 129 hdp->mode = RRIP_MODE(px_ptr); 130 hdp->nlink = RRIP_NLINK(px_ptr); 131 hdp->uid = RRIP_UID(px_ptr); 132 hdp->gid = RRIP_GID(px_ptr); 133 134 hdp->type = IFTOVT(hdp->mode); 135 136 return (px_ptr + SUF_LEN(px_ptr)); 137 } 138 139 /* 140 * rrip_file_time() 141 * 142 * support function for rrip_file_time() 143 * 144 * This function decides whether to parse the times in a long time form 145 * (17 bytes) or a short time form (7 bytes). These time formats are 146 * defined in the ISO 9660 specification. 147 */ 148 static void 149 form_time(int time_length, uchar_t *file_time, struct timeval *tvp) 150 { 151 if (time_length == ISO_DATE_LEN) 152 hs_parse_longdate(file_time, tvp); 153 else 154 hs_parse_dirdate(file_time, tvp); 155 156 } 157 158 /* 159 * rrip_file_time() 160 * 161 * sig_handler() for RRIP signature RRIP_TF 162 * 163 * This function parses out the file time attributes of a file from the 164 * "TI" SUF. The times it parses are : st_mtime, st_atime and st_ctime. 165 * 166 * The function form_time is a support function only used in this 167 * function. 168 */ 169 uchar_t * 170 rrip_file_time(sig_args_t *sig_args_p) 171 { 172 uchar_t *tf_ptr = sig_args_p->SUF_ptr; 173 174 if (IS_TIME_BIT_SET(RRIP_TF_FLAGS(tf_ptr), RRIP_TF_ACCESS_BIT)) { 175 form_time(RRIP_TF_TIME_LENGTH(tf_ptr), 176 RRIP_tf_access(tf_ptr), 177 &sig_args_p->hdp->adate); 178 } 179 180 if (IS_TIME_BIT_SET(RRIP_TF_FLAGS(tf_ptr), RRIP_TF_MODIFY_BIT)) { 181 form_time(RRIP_TF_TIME_LENGTH(tf_ptr), RRIP_tf_modify(tf_ptr), 182 &sig_args_p->hdp->mdate); 183 } 184 185 if (IS_TIME_BIT_SET(RRIP_TF_FLAGS(tf_ptr), RRIP_TF_ATTRIBUTES_BIT)) { 186 form_time(RRIP_TF_TIME_LENGTH(tf_ptr), 187 RRIP_tf_attributes(tf_ptr), 188 &sig_args_p->hdp->cdate); 189 } 190 191 return (tf_ptr + SUF_LEN(tf_ptr)); 192 } 193 194 195 196 /* 197 * name_parse() 198 * 199 * This is a generic fuction used for sym links and filenames. The 200 * flags passed to it effect the way the name/component field is parsed. 201 * 202 * The return value will be the NAME_CONTINUE or NAME_CHANGE value. 203 * 204 */ 205 static void 206 name_parse( 207 int rrip_flags, /* component/name flag */ 208 uchar_t *SUA_string, /* string from SUA */ 209 size_t SUA_string_len, /* length of SUA string */ 210 uchar_t *dst, /* string to copy to */ 211 int *dst_lenp, /* ptr to cur. str len */ 212 ulong_t *name_flags_p, /* internal name flags */ 213 int dst_size) /* limit dest string to */ 214 /* this value */ 215 { 216 if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_ROOT)) 217 (void) strcpy((char *)dst, "/"); 218 219 if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_CURRENT)) { 220 SUA_string = (uchar_t *)"."; 221 SUA_string_len = 1; 222 } 223 224 if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_PARENT)) { 225 SUA_string = (uchar_t *)".."; 226 SUA_string_len = 2; 227 } 228 229 /* 230 * XXX 231 * For now, ignore the following flags and return. 232 * have to figure out how to get host name in kernel. 233 * Unsure if this even should be done. 234 */ 235 if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_VOLROOT) || 236 IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_HOST)) { 237 cmn_err(CE_NOTE, 238 "VOLUME ROOT and NAME_HOST currently unsupported\n"); 239 return; 240 } 241 242 /* 243 * Since SUA_string isn't NULL terminated, we use strlcat() 244 * to add the trailing NULL byte. Defensive programming, don't 245 * ever overwrite beyond the end of the destination buffer, 246 * and neither attempt to read beyond the end of SUA_string. 247 * We assume the caller properly validates SUA_string_len as 248 * we have no way of doing so. 249 * Note for corrupted filesystems, SUA_string may contain 250 * NULL bytes. If that happens, the destination string length 251 * returned will be larger than the "actual" length, since 252 * strlcat() terminates when encountering the NULL byte. 253 * This causes no harm (apart from filenames not being reported 254 * 'correctly', but then what is correct on a corrupted fs ?) 255 * so we don't bother assigning strlen(dst) to *dst_lenp. 256 */ 257 *dst_lenp = MIN(dst_size, strlen((char *)dst) + SUA_string_len + 1); 258 (void) strlcat((char *)dst, (char *)SUA_string, (*dst_lenp)--); 259 260 if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_CONTINUE)) 261 SET_NAME_BIT(*(name_flags_p), RRIP_NAME_CONTINUE); 262 else 263 SET_NAME_BIT(*(name_flags_p), RRIP_NAME_CHANGE); 264 265 } 266 267 /* 268 * rrip_name() 269 * 270 * sig_handler() for RRIP signature RRIP_NM 271 * 272 * This function handles the name of the current file. It is case 273 * sensitive to whatever was put into the field and does NO 274 * translation. It will take whatever characters were in the field. 275 * 276 * Because the flags effect the way the name is parsed the same way 277 * that the sym_link component parsing is done, we will use the same 278 * function to do the actual parsing. 279 */ 280 uchar_t * 281 rrip_name(sig_args_t *sig_args_p) 282 { 283 uchar_t *nm_ptr = sig_args_p->SUF_ptr; 284 285 if ((sig_args_p->name_p == (uchar_t *)NULL) || 286 (sig_args_p->name_len_p == (int *)NULL)) 287 goto end; 288 /* 289 * If we have a "." or ".." directory, we should not look for 290 * an alternate name 291 */ 292 if (HDE_NAME_LEN(sig_args_p->dirp) == 1) { 293 if (*((char *)HDE_name(sig_args_p->dirp)) == '\0') { 294 (void) strcpy((char *)sig_args_p->name_p, "."); 295 *sig_args_p->name_len_p = 1; 296 goto end; 297 } else if (*((char *)HDE_name(sig_args_p->dirp)) == '\1') { 298 (void) strcpy((char *)sig_args_p->name_p, ".."); 299 *sig_args_p->name_len_p = 2; 300 goto end; 301 } 302 } 303 304 name_parse((int)RRIP_NAME_FLAGS(nm_ptr), RRIP_name(nm_ptr), 305 (size_t)RRIP_NAME_LEN(nm_ptr), sig_args_p->name_p, 306 sig_args_p->name_len_p, &(sig_args_p->name_flags), 307 MAXNAMELEN); 308 309 end: 310 return (nm_ptr + SUF_LEN(nm_ptr)); 311 } 312 313 314 /* 315 * rrip_sym_link() 316 * 317 * sig_handler() for RRIP signature RRIP_SL 318 * 319 * creates a symlink buffer to simulate sym_links. 320 */ 321 uchar_t * 322 rrip_sym_link(sig_args_t *sig_args_p) 323 { 324 uchar_t *sl_ptr = sig_args_p->SUF_ptr; 325 uchar_t *comp_ptr; 326 char *tmp_sym_link; 327 struct hs_direntry *hdp = sig_args_p->hdp; 328 int sym_link_len; 329 char *sym_link; 330 331 if (hdp->type != VLNK) 332 goto end; 333 334 /* 335 * If the sym link has already been created, don't recreate it 336 */ 337 if (IS_NAME_BIT_SET(sig_args_p->name_flags, RRIP_SYM_LINK_COMPLETE)) 338 goto end; 339 340 sym_link = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP); 341 342 /* 343 * If there is an original string put it into sym_link[], otherwise 344 * initialize sym_link[] to the empty string. 345 */ 346 if (hdp->sym_link != (char *)NULL) { 347 sym_link_len = (int)strlen(strcpy(sym_link, hdp->sym_link)); 348 } else { 349 sym_link[0] = '\0'; 350 sym_link_len = 0; 351 } 352 353 /* for all components */ 354 for (comp_ptr = RRIP_sl_comp(sl_ptr); 355 comp_ptr < (sl_ptr + SUF_LEN(sl_ptr)); 356 comp_ptr += RRIP_COMP_LEN(comp_ptr)) { 357 358 name_parse((int)RRIP_COMP_FLAGS(comp_ptr), 359 RRIP_comp(comp_ptr), 360 (size_t)RRIP_COMP_NAME_LEN(comp_ptr), (uchar_t *)sym_link, 361 &sym_link_len, &(sig_args_p->name_flags), 362 MAXPATHLEN); 363 364 /* 365 * If the component is continued, Don't put a 366 * '/' in the pathname, but do NULL terminate it. 367 * And avoid 2 '//' in a row, or if '/' was wanted 368 */ 369 if (IS_NAME_BIT_SET(RRIP_COMP_FLAGS(comp_ptr), 370 RRIP_NAME_CONTINUE) || 371 (sym_link[sym_link_len - 1] == '/')) { 372 373 sym_link[sym_link_len] = '\0'; 374 } else { 375 sym_link[sym_link_len] = '/'; 376 sym_link[sym_link_len + 1] = '\0'; 377 378 /* add 1 to sym_link_len for '/' */ 379 sym_link_len++; 380 } 381 382 } 383 384 /* 385 * take out the last slash 386 */ 387 if (sym_link[sym_link_len - 1] == '/') 388 sym_link[--sym_link_len] = '\0'; 389 390 /* 391 * if no memory has been allocated, get some, otherwise, append 392 * to the current allocation 393 */ 394 395 tmp_sym_link = kmem_alloc(SYM_LINK_LEN(sym_link), KM_SLEEP); 396 397 (void) strcpy(tmp_sym_link, sym_link); 398 399 if (hdp->sym_link != (char *)NULL) 400 kmem_free(hdp->sym_link, (size_t)(hdp->ext_size + 1)); 401 402 hdp->sym_link = (char *)&tmp_sym_link[0]; 403 /* the size of a symlink is its length */ 404 hdp->ext_size = (uint_t)strlen(tmp_sym_link); 405 406 if (!IS_NAME_BIT_SET(RRIP_SL_FLAGS(sl_ptr), RRIP_NAME_CONTINUE)) { 407 /* reached the end of the symbolic link */ 408 SET_NAME_BIT(sig_args_p->name_flags, RRIP_SYM_LINK_COMPLETE); 409 } 410 411 kmem_free(sym_link, MAXPATHLEN + 1); 412 end: 413 return (sl_ptr + SUF_LEN(sl_ptr)); 414 } 415 416 /* 417 * rrip_namecopy() 418 * 419 * This function will copy the rrip name to the "to" buffer, if it 420 * exists. 421 * 422 * XXX - We should speed this up by implementing the search in 423 * parse_sua(). It works right now, so I don't want to mess with it. 424 */ 425 int 426 rrip_namecopy( 427 char *from, /* name to copy */ 428 char *to, /* string to copy "from" to */ 429 char *tmp_name, /* temp storage for original name */ 430 uchar_t *dirp, /* directory entry pointer */ 431 struct hsfs *fsp, /* filesystem pointer */ 432 struct hs_direntry *hdp) /* directory entry pointer to put */ 433 /* all that good info in */ 434 { 435 int size = 0; 436 int change_flag = 0; 437 int ret_val; 438 439 if ((to == (char *)NULL) || 440 (from == (char *)NULL) || 441 (dirp == (uchar_t *)NULL)) { 442 return (0); 443 } 444 445 /* special handling for '.' and '..' */ 446 447 if (HDE_NAME_LEN(dirp) == 1) { 448 if (*((char *)HDE_name(dirp)) == '\0') { 449 (void) strcpy(to, "."); 450 return (1); 451 } else if (*((char *)HDE_name(dirp)) == '\1') { 452 (void) strcpy(to, ".."); 453 return (2); 454 } 455 } 456 457 458 ret_val = parse_sua((uchar_t *)to, &size, &change_flag, dirp, 459 hdp, fsp, (uchar_t *)NULL, NULL); 460 461 if (IS_NAME_BIT_SET(change_flag, RRIP_NAME_CHANGE) && !ret_val) 462 return (size); 463 464 /* 465 * Well, the name was not found 466 * 467 * make rripname an upper case "nm" (to), so that 468 * we can compare it the current HDE_DIR_NAME() 469 * without nuking the original "nm", for future case 470 * sensitive name comparing 471 */ 472 (void) strcpy(tmp_name, from); /* keep original */ 473 size = hs_uppercase_copy(tmp_name, from, (int)strlen(from)); 474 475 return (-1); 476 } 477 478 479 480 /* 481 * rrip_reloc_dir() 482 * 483 * This function is fairly bogus. All it does is cause a failure of 484 * the hs_parsedir, so that no vnode will be made for it and 485 * essentially, the directory will no longer be seen. This is part 486 * of the directory hierarchy mess, where the relocated directory will 487 * be hidden as far as ISO 9660 is concerned. When we hit the child 488 * link "CL" SUF, then we will read the new directory. 489 */ 490 uchar_t * 491 rrip_reloc_dir(sig_args_t *sig_args_p) 492 { 493 uchar_t *re_ptr = sig_args_p->SUF_ptr; 494 495 sig_args_p->flags = RELOC_DIR; 496 497 return (re_ptr + SUF_LEN(re_ptr)); 498 } 499 500 501 502 /* 503 * rrip_child_link() 504 * 505 * This is the child link part of the directory hierarchy stuff and 506 * this does not really do much anyway. All it does is read the 507 * directory entry that the child link SUF contains. All should be 508 * fine then. 509 */ 510 uchar_t * 511 rrip_child_link(sig_args_t *sig_args_p) 512 { 513 uchar_t *cl_ptr = sig_args_p->SUF_ptr; 514 515 sig_args_p->hdp->ext_lbn = RRIP_CHILD_LBN(cl_ptr); 516 517 hs_filldirent(sig_args_p->fsp->hsfs_rootvp, sig_args_p->hdp); 518 519 sig_args_p->flags = 0; 520 521 return (cl_ptr + SUF_LEN(cl_ptr)); 522 } 523 524 525 /* 526 * rrip_parent_link() 527 * 528 * This is the parent link part of the directory hierarchy stuff and 529 * this does not really do much anyway. All it does is read the 530 * directory entry that the parent link SUF contains. All should be 531 * fine then. 532 */ 533 uchar_t * 534 rrip_parent_link(sig_args_t *sig_args_p) 535 { 536 uchar_t *pl_ptr = sig_args_p->SUF_ptr; 537 538 sig_args_p->hdp->ext_lbn = RRIP_PARENT_LBN(pl_ptr); 539 540 hs_filldirent(sig_args_p->fsp->hsfs_rootvp, sig_args_p->hdp); 541 542 sig_args_p->flags = 0; 543 544 return (pl_ptr + SUF_LEN(pl_ptr)); 545 } 546 547 548 /* 549 * rrip_rock_ridge() 550 * 551 * This function is supposed to aid in speed of the filesystem. 552 * 553 * XXX - It is only here as a place holder so far. 554 */ 555 uchar_t * 556 rrip_rock_ridge(sig_args_t *sig_args_p) 557 { 558 uchar_t *rr_ptr = sig_args_p->SUF_ptr; 559 560 return (rr_ptr + SUF_LEN(rr_ptr)); 561 } 562