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 || SUF_LEN(sig_string) <= 0) { 322 return (END_OF_SUA); 323 } 324 325 } /* while */ 326 327 return (END_OF_SUA); 328 } 329 330 /* 331 * hs_fill_root_dirent() 332 * 333 * 334 * This function reads the root directory extent to get to the SUA of 335 * the "." entry of the root directory. It the checks to see if the 336 * susp is implemented. 337 */ 338 void 339 hs_check_root_dirent(struct vnode *vp, struct hs_direntry *hdp) 340 { 341 struct buf *secbp; 342 uchar_t *root_ptr; 343 uchar_t *secp; 344 uint_t secno; 345 offset_t secoff; 346 sig_args_t sig_args; 347 struct hsfs *fsp; 348 int error; 349 350 if (vp->v_type != VDIR) { 351 cmn_err(CE_NOTE, 352 "hs_check_root_dirent: vp (0x%p) not a directory", 353 (void *)vp); 354 return; 355 } 356 357 bzero((caddr_t)&sig_args, sizeof (sig_args)); 358 359 fsp = VFS_TO_HSFS(vp->v_vfsp); 360 secno = LBN_TO_SEC(hdp->ext_lbn+hdp->xar_len, vp->v_vfsp); 361 secoff = LBN_TO_BYTE(hdp->ext_lbn+hdp->xar_len, vp->v_vfsp) & 362 MAXHSOFFSET; 363 secbp = bread(fsp->hsfs_devvp->v_rdev, secno * 4, HS_SECTOR_SIZE); 364 error = geterror(secbp); 365 366 if (error != 0) { 367 cmn_err(CE_NOTE, 368 "hs_check_root_dirent: bread: error=(%d)", error); 369 goto end; 370 } 371 372 secp = (uchar_t *)secbp->b_un.b_addr; 373 root_ptr = &secp[secoff]; 374 375 /* quick check */ 376 if (hdp->ext_lbn != HDE_EXT_LBN(root_ptr)) { 377 cmn_err(CE_NOTE, "hs_check_root_dirent: dirent not match\n"); 378 /* keep on going */ 379 } 380 381 /* 382 * Here, we know that the "." entry is the first in the sector 383 * just read (ISO 9660). Let's now check for the sharing 384 * protocol and set call the susp sig_handler() if we should. 385 * Then we run through the hs_parsedir() function to catch all 386 * the other possibilities of SUSP fields and continuations. 387 * 388 * If there is not SUA area, just return, and assume ISO. 389 */ 390 391 if (IDE_SUA_LEN(root_ptr) == 0) 392 goto end; 393 394 if (strncmp(SUSP_SP, (char *)IDE_sys_use_area(root_ptr), 395 SUF_SIG_LEN) == 0) { 396 /* 397 * We have a match of the sharing signature, so let's 398 * call the sig_handler to do what is necessary. We can 399 * ignore the return value, as implemented bits are set. 400 */ 401 sig_args.SUF_ptr = IDE_sys_use_area(root_ptr); 402 sig_args.fsp = fsp; 403 404 if ((susp_sp->sig_handler)(&sig_args) == (uchar_t *)NULL) { 405 goto end; 406 } 407 } else 408 goto end; 409 410 (void) hs_parsedir(fsp, root_ptr, hdp, (char *)NULL, (int *)NULL); 411 412 /* 413 * If we did not get at least 1 extension, let's assume ISO and 414 * NULL out the implementation bits. 415 */ 416 if (fsp->hsfs_ext_impl <= 1L) 417 fsp->hsfs_ext_impl = 0L; 418 419 end: 420 brelse(secbp); 421 } 422 423 424 /* 425 * get_cont_area() 426 * 427 * This function allocates a memory block, if necessary, and reads the 428 * continuation area into the allocated space. 429 * 430 * Return value : 0 if the read and allocation went OK. 431 * 1 if there was an error. 432 */ 433 static int 434 get_cont_area(struct hsfs *fsp, uchar_t **buf_pp, cont_info_t *cont_info_p) 435 { 436 struct buf *secbp; 437 int error; 438 uint_t secno; 439 440 /* 441 * Guard against invalid continuation area records. 442 * Both cont_offset and cont_len must be no longer than 443 * HS_SECTOR_SIZE. If they are, return an error. 444 */ 445 if (cont_info_p->cont_offset > HS_SECTOR_SIZE || 446 cont_info_p->cont_len > HS_SECTOR_SIZE) { 447 cmn_err(CE_NOTE, "get_cont_area: invalid offset/length"); 448 return (1); 449 } 450 451 if (*buf_pp == (uchar_t *)NULL) 452 *buf_pp = kmem_alloc((size_t)HS_SECTOR_SIZE, KM_SLEEP); 453 454 secno = (uint_t)LBN_TO_SEC(cont_info_p->cont_lbn, fsp->hsfs_vfs); 455 secbp = bread(fsp->hsfs_devvp->v_rdev, secno * 4, HS_SECTOR_SIZE); 456 error = geterror(secbp); 457 458 if (error != 0) { 459 cmn_err(CE_NOTE, "get_cont_area: bread: error=(%d)", error); 460 brelse(secbp); 461 return (1); 462 } 463 464 /* 465 * This continuation area does not extend into the next sector 466 * so just copy the data to the buffer. 467 */ 468 if ((cont_info_p->cont_offset + cont_info_p->cont_len) <= 469 HS_SECTOR_SIZE) { 470 bcopy(secbp->b_un.b_addr, (char *)*buf_pp, HS_SECTOR_SIZE); 471 } 472 /* 473 * This continuation area extends into the next sector so we 474 * need to do some dancing: 475 * 476 * - zero the return buffer so nothing random is returned 477 * - copy the partial data to the *beginning* of the return buffer 478 * - release the first sector's buffer 479 * - read the next sector 480 * - copy the remainder of the data to the return buffer 481 */ 482 else { 483 uint_t partial_size; 484 485 bzero((char *)*buf_pp, HS_SECTOR_SIZE); 486 partial_size = HS_SECTOR_SIZE - cont_info_p->cont_offset; 487 bcopy(&secbp->b_un.b_addr[cont_info_p->cont_offset], 488 (char *)*buf_pp, partial_size); 489 cont_info_p->cont_offset = 0; 490 brelse(secbp); 491 492 secbp = bread(fsp->hsfs_devvp->v_rdev, (secno + 1) * 4, 493 HS_SECTOR_SIZE); 494 error = geterror(secbp); 495 if (error != 0) { 496 cmn_err(CE_NOTE, "get_cont_area: bread(2): error=(%d)", 497 error); 498 brelse(secbp); 499 return (1); 500 } 501 bcopy(secbp->b_un.b_addr, (char *)&(*buf_pp)[partial_size], 502 cont_info_p->cont_len - partial_size); 503 } 504 505 brelse(secbp); 506 return (0); 507 } 508 509 510 /* 511 * free_cont_area 512 * 513 * simple function to just free up memory, if it exists 514 * 515 */ 516 static void 517 free_cont_area(uchar_t *cont_p) 518 { 519 if (cont_p) 520 (void) kmem_free((caddr_t)cont_p, (size_t)HS_SECTOR_SIZE); 521 cont_p = (uchar_t *)NULL; 522 } 523