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 * System Use Sharing protocol subroutines for High Sierra filesystem 24 * 25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 26 * Use is subject to license terms. 27 */ 28 29 #pragma ident "%Z%%M% %I% %E% SMI" 30 31 #include <sys/types.h> 32 #include <sys/t_lock.h> 33 #include <sys/param.h> 34 #include <sys/systm.h> 35 #include <sys/sysmacros.h> 36 #include <sys/kmem.h> 37 #include <sys/signal.h> 38 #include <sys/user.h> 39 #include <sys/proc.h> 40 #include <sys/disp.h> 41 #include <sys/buf.h> 42 #include <sys/pathname.h> 43 #include <sys/vfs.h> 44 #include <sys/vnode.h> 45 #include <sys/file.h> 46 #include <sys/uio.h> 47 #include <sys/conf.h> 48 49 #include <vm/page.h> 50 51 #include <sys/fs/hsfs_spec.h> 52 #include <sys/fs/hsfs_isospec.h> 53 #include <sys/fs/hsfs_node.h> 54 #include <sys/fs/hsfs_impl.h> 55 #include <sys/fs/hsfs_susp.h> 56 #include <sys/fs/hsfs_rrip.h> 57 58 #include <sys/statvfs.h> 59 #include <sys/mount.h> 60 #include <sys/swap.h> 61 #include <sys/errno.h> 62 #include <sys/debug.h> 63 #include "fs/fs_subr.h" 64 #include <sys/cmn_err.h> 65 66 /* static declarations */ 67 static void free_cont_area(uchar_t *); 68 static int get_cont_area(struct hsfs *, uchar_t **, cont_info_t *); 69 static int parse_signatures(sig_args_t *, uint_t, uchar_t *, int); 70 71 /* 72 * parse_sua() 73 * 74 * This is the main SUSP routine, that gets all the SUA areas and 75 * continuations. It calls parse_signatures() to actually interpret 76 * the signature fields. 77 * 78 * XXX - need to implement signature searching to speed things up and 79 * which is needed for the api, which isn't done yet. 80 */ 81 int 82 parse_sua( 83 uchar_t *name_p, /* location to copy name */ 84 int *name_len_p, /* location to put name len */ 85 int *name_change_p, /* flags to signal name chg */ 86 uchar_t *dirp, /* pointer to ISO dir entry */ 87 struct hs_direntry *hdp, /* loc to store dir info */ 88 struct hsfs *fsp, /* filesystem pointer */ 89 uchar_t *search_sig, /* signature to search for */ 90 int search_num) /* n^th sig to search for */ 91 { 92 uchar_t *SUA_p = IDE_sys_use_area(dirp); 93 int SUA_len = IDE_SUA_LEN(dirp); 94 uchar_t *tmp_SUA_p = (SUA_p + fsp->hsfs_sua_off); 95 int tmp_SUA_len = (SUA_len - fsp->hsfs_sua_off); 96 short ret_val = -1; 97 uchar_t *cont_p = (uchar_t *)NULL; 98 sig_args_t sig_args; 99 cont_info_t cont_info; 100 101 /* 102 * If there is no SUA, just return, no error 103 */ 104 105 if (SUA_len == 0) 106 return (0); 107 108 /* 109 * Make sure that the continuation lenth is zero, as that is 110 * the way to tell if we must grab another continuation area. 111 */ 112 bzero((char *)&cont_info, sizeof (cont_info)); 113 114 sig_args.dirp = dirp; 115 sig_args.name_p = name_p; 116 sig_args.name_len_p = name_len_p; 117 sig_args.SUF_ptr = tmp_SUA_p; 118 sig_args.hdp = hdp; 119 sig_args.fsp = fsp; 120 sig_args.cont_info_p = &cont_info; 121 sig_args.flags = 0; 122 sig_args.name_flags = 0; 123 124 /* 125 * Get ready to put in a new name. If no "NM" is found, then 126 * hs_namecopy will come to the rescue. Make sure you don't 127 * have NULL names, also. 128 */ 129 if (name_p) 130 *(name_p) = '\0'; 131 if (name_len_p) 132 *(name_len_p) = 0; 133 134 while (ret_val == -1) { 135 switch (parse_signatures(&sig_args, tmp_SUA_len, search_sig, 136 search_num)) { 137 case END_OF_SUA : 138 if (cont_info.cont_len) { 139 140 if (get_cont_area(fsp, &cont_p, &cont_info)) { 141 ret_val = 1; 142 goto clean_up; 143 } 144 145 sig_args.SUF_ptr = cont_p + 146 cont_info.cont_offset; 147 148 tmp_SUA_len = cont_info.cont_len; 149 cont_info.cont_len = 0; 150 151 continue; 152 } 153 sig_args.flags = 0; /* reset */ 154 ret_val = 0; /* keep going */ 155 break; 156 case SUA_NULL_POINTER: 157 ret_val = SUA_NULL_POINTER; 158 goto clean_up; 159 case SUA_ENOMEM: 160 ret_val = SUA_ENOMEM; 161 goto clean_up; 162 case SUA_EINVAL: 163 ret_val = SUA_EINVAL; 164 goto clean_up; 165 case RELOC_DIR: 166 ret_val = RELOC_DIR; 167 goto clean_up; 168 } 169 } 170 171 if (ret_val != 0) 172 goto clean_up; 173 174 if (IS_NAME_BIT_SET(sig_args.name_flags, RRIP_NAME_CHANGE)) 175 SET_NAME_BIT(*(name_change_p), RRIP_NAME_CHANGE); 176 177 clean_up: 178 free_cont_area(cont_p); 179 return (ret_val); 180 181 } 182 183 /* 184 * parse_signatures() 185 * 186 * Find the correct handling function for the signature string that is 187 * passed to this function. 188 * 189 * signature searching: 190 * 191 * The two arguments of search_sig and search_num are for finding the 192 * search_num^th occurance of the signature search_sig. This will come 193 * in handy with searching for the "NM" field and is part of the api 194 * for rrip (which really can be used for any extension). 195 */ 196 /*ARGSUSED*/ 197 static int 198 parse_signatures( 199 sig_args_t *sig_args_p, 200 uint_t SUA_len, 201 uchar_t *search_sig, /* possible signature to search for */ 202 int search_num) /* n^th occurance of search_sig to */ 203 /* search for */ 204 { 205 uchar_t *sig_string = sig_args_p->SUF_ptr; 206 extension_name_t *extnp; 207 ext_signature_t *ext_sigp; 208 int impl_bit_num = 0; 209 uint_t SUA_rem = SUA_len; /* SUA length */ 210 /* remaining to be parsed */ 211 212 /* This should never happen ... just so we don't panic, literally */ 213 if (sig_string == (uchar_t *)NULL) 214 return (SUA_NULL_POINTER); 215 216 /* 217 * Until the end of SUA, search for the signatures 218 * (check for end of SUA (2 consecutive NULL bytes)) or the 219 * remaining length of the SUA is <= 3. The minimum signature 220 * field is 4. 221 */ 222 223 while ((SUA_rem >= SUF_MIN_LEN) && (*sig_string != '\0') && 224 (*(sig_string + 1) != '\0')) { 225 226 /* 227 * Find appropriate extension and signature table 228 */ 229 for (extnp = extension_name_table, impl_bit_num = 0; 230 extnp->extension_name != (char *)NULL; 231 extnp++, impl_bit_num++) { 232 233 /* 234 * look at an extension only if it is implemented 235 * on the CD-ROM 236 */ 237 if (!IS_IMPL_BIT_SET(sig_args_p->fsp, impl_bit_num)) 238 continue; 239 240 /* 241 * Find the appropriate signature 242 */ 243 for (ext_sigp = extnp->signature_table; 244 ext_sigp->ext_signature != (char *)NULL; 245 ext_sigp++) { 246 247 if (strncmp((char *)sig_string, 248 ext_sigp->ext_signature, 249 SUF_SIG_LEN) == 0) { 250 251 SUA_rem -= SUF_LEN(sig_string); 252 253 /* 254 * The SUA_len parameter specifies the 255 * length of the SUA that the kernel 256 * expects. There is also a length 257 * encoded in the SUA data. If they 258 * do not agree, bail out. 259 */ 260 if (SUA_len < SUF_LEN(sig_string)) { 261 cmn_err(CE_NOTE, 262 "parse_signatures: SUA length too big: " 263 "expected=%d, found=%d", 264 SUA_len, 265 SUF_LEN(sig_string)); 266 return (SUA_EINVAL); 267 } 268 269 sig_args_p->SUF_ptr = sig_string; 270 sig_string = 271 (ext_sigp->sig_handler)(sig_args_p); 272 273 switch (sig_args_p->flags) { 274 case END_OF_SUA : 275 return (END_OF_SUA); 276 case SUA_ENOMEM : 277 return (SUA_ENOMEM); 278 case SUA_EINVAL : 279 return (SUA_EINVAL); 280 case RELOC_DIR : 281 return (RELOC_DIR); 282 default : 283 #if NAME_SEARCH 284 case NAME_CONTINUE : 285 /* nothing for now */ 286 case NAME_CHANGE : 287 /* nothing for now */ 288 #endif 289 break; 290 } 291 292 /* reset to be zero */ 293 294 sig_args_p->flags = 0; 295 goto next_signature; 296 } 297 298 /* off to the next signature .... */ 299 300 } /* for ext_sigp */ 301 302 } /* for extnp (extension parsing) */ 303 304 /* 305 * Opps, did not find this signature. We must 306 * advance on the the next signature in the SUA 307 * and pray to persumedly omniscient, omnipresent, 308 * almighty transcendental being(s) that the next 309 * record is in the susp format, or we get hosed. 310 */ 311 if (SUA_rem < SUF_MIN_LEN) 312 return (END_OF_SUA); 313 314 SUA_rem -= SUF_LEN(sig_string); 315 sig_string += SUF_LEN(sig_string); 316 317 next_signature: 318 /* 319 * Failsafe 320 */ 321 if (SUA_rem < SUF_MIN_LEN || 322 sig_string == NULL || SUF_LEN(sig_string) <= 0) { 323 return (END_OF_SUA); 324 } 325 326 } /* while */ 327 328 return (END_OF_SUA); 329 } 330 331 /* 332 * hs_fill_root_dirent() 333 * 334 * 335 * This function reads the root directory extent to get to the SUA of 336 * the "." entry of the root directory. It the checks to see if the 337 * susp is implemented. 338 */ 339 void 340 hs_check_root_dirent(struct vnode *vp, struct hs_direntry *hdp) 341 { 342 struct buf *secbp; 343 uchar_t *root_ptr; 344 uchar_t *secp; 345 uint_t secno; 346 offset_t secoff; 347 sig_args_t sig_args; 348 struct hsfs *fsp; 349 int error; 350 351 if (vp->v_type != VDIR) { 352 cmn_err(CE_NOTE, 353 "hs_check_root_dirent: vp (0x%p) not a directory", 354 (void *)vp); 355 return; 356 } 357 358 bzero((caddr_t)&sig_args, sizeof (sig_args)); 359 360 fsp = VFS_TO_HSFS(vp->v_vfsp); 361 secno = LBN_TO_SEC(hdp->ext_lbn+hdp->xar_len, vp->v_vfsp); 362 secoff = LBN_TO_BYTE(hdp->ext_lbn+hdp->xar_len, vp->v_vfsp) & 363 MAXHSOFFSET; 364 secbp = bread(fsp->hsfs_devvp->v_rdev, secno * 4, HS_SECTOR_SIZE); 365 error = geterror(secbp); 366 367 if (error != 0) { 368 cmn_err(CE_NOTE, 369 "hs_check_root_dirent: bread: error=(%d)", error); 370 goto end; 371 } 372 373 secp = (uchar_t *)secbp->b_un.b_addr; 374 root_ptr = &secp[secoff]; 375 376 /* quick check */ 377 if (hdp->ext_lbn != HDE_EXT_LBN(root_ptr)) { 378 cmn_err(CE_NOTE, "hs_check_root_dirent: dirent not match\n"); 379 /* keep on going */ 380 } 381 382 /* 383 * Here, we know that the "." entry is the first in the sector 384 * just read (ISO 9660). Let's now check for the sharing 385 * protocol and set call the susp sig_handler() if we should. 386 * Then we run through the hs_parsedir() function to catch all 387 * the other possibilities of SUSP fields and continuations. 388 * 389 * If there is not SUA area, just return, and assume ISO. 390 */ 391 392 if (IDE_SUA_LEN(root_ptr) == 0) 393 goto end; 394 395 if (strncmp(SUSP_SP, (char *)IDE_sys_use_area(root_ptr), 396 SUF_SIG_LEN) == 0) { 397 /* 398 * We have a match of the sharing signature, so let's 399 * call the sig_handler to do what is necessary. We can 400 * ignore the return value, as implemented bits are set. 401 */ 402 sig_args.SUF_ptr = IDE_sys_use_area(root_ptr); 403 sig_args.fsp = fsp; 404 405 if ((susp_sp->sig_handler)(&sig_args) == (uchar_t *)NULL) { 406 goto end; 407 } 408 } else 409 goto end; 410 411 (void) hs_parsedir(fsp, root_ptr, hdp, (char *)NULL, (int *)NULL); 412 413 /* 414 * If we did not get at least 1 extension, let's assume ISO and 415 * NULL out the implementation bits. 416 */ 417 if (fsp->hsfs_ext_impl <= 1L) 418 fsp->hsfs_ext_impl = 0L; 419 420 end: 421 brelse(secbp); 422 } 423 424 425 /* 426 * get_cont_area() 427 * 428 * This function allocates a memory block, if necessary, and reads the 429 * continuation area into the allocated space. 430 * 431 * Return value : 0 if the read and allocation went OK. 432 * 1 if there was an error. 433 */ 434 static int 435 get_cont_area(struct hsfs *fsp, uchar_t **buf_pp, cont_info_t *cont_info_p) 436 { 437 struct buf *secbp; 438 int error; 439 uint_t secno; 440 441 /* 442 * Guard against invalid continuation area records. 443 * Both cont_offset and cont_len must be no longer than 444 * HS_SECTOR_SIZE. If they are, return an error. 445 */ 446 if (cont_info_p->cont_offset > HS_SECTOR_SIZE || 447 cont_info_p->cont_len > HS_SECTOR_SIZE) { 448 cmn_err(CE_NOTE, "get_cont_area: invalid offset/length"); 449 return (1); 450 } 451 452 if (*buf_pp == (uchar_t *)NULL) 453 *buf_pp = kmem_alloc((size_t)HS_SECTOR_SIZE, KM_SLEEP); 454 455 secno = (uint_t)LBN_TO_SEC(cont_info_p->cont_lbn, fsp->hsfs_vfs); 456 secbp = bread(fsp->hsfs_devvp->v_rdev, secno * 4, HS_SECTOR_SIZE); 457 error = geterror(secbp); 458 459 if (error != 0) { 460 cmn_err(CE_NOTE, "get_cont_area: bread: error=(%d)", error); 461 brelse(secbp); 462 return (1); 463 } 464 465 /* 466 * This continuation area does not extend into the next sector 467 * so just copy the data to the buffer. 468 */ 469 if ((cont_info_p->cont_offset + cont_info_p->cont_len) <= 470 HS_SECTOR_SIZE) { 471 bcopy(secbp->b_un.b_addr, (char *)*buf_pp, HS_SECTOR_SIZE); 472 } 473 /* 474 * This continuation area extends into the next sector so we 475 * need to do some dancing: 476 * 477 * - zero the return buffer so nothing random is returned 478 * - copy the partial data to the *beginning* of the return buffer 479 * - release the first sector's buffer 480 * - read the next sector 481 * - copy the remainder of the data to the return buffer 482 */ 483 else { 484 uint_t partial_size; 485 486 bzero((char *)*buf_pp, HS_SECTOR_SIZE); 487 partial_size = HS_SECTOR_SIZE - cont_info_p->cont_offset; 488 bcopy(&secbp->b_un.b_addr[cont_info_p->cont_offset], 489 (char *)*buf_pp, partial_size); 490 cont_info_p->cont_offset = 0; 491 brelse(secbp); 492 493 secbp = bread(fsp->hsfs_devvp->v_rdev, (secno + 1) * 4, 494 HS_SECTOR_SIZE); 495 error = geterror(secbp); 496 if (error != 0) { 497 cmn_err(CE_NOTE, "get_cont_area: bread(2): error=(%d)", 498 error); 499 brelse(secbp); 500 return (1); 501 } 502 bcopy(secbp->b_un.b_addr, (char *)&(*buf_pp)[partial_size], 503 cont_info_p->cont_len - partial_size); 504 } 505 506 brelse(secbp); 507 return (0); 508 } 509 510 511 /* 512 * free_cont_area 513 * 514 * simple function to just free up memory, if it exists 515 * 516 */ 517 static void 518 free_cont_area(uchar_t *cont_p) 519 { 520 if (cont_p) 521 (void) kmem_free((caddr_t)cont_p, (size_t)HS_SECTOR_SIZE); 522 cont_p = (uchar_t *)NULL; 523 } 524