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 (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   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.
  12  *
  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]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
  23  * Use is subject to license terms.
  24  */
  25 
  26 /*
  27  * Rock Ridge extensions to the System Use Sharing protocol
  28  * for the High Sierra filesystem
  29  */
  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/kmem.h>
  36 #include <sys/signal.h>
  37 #include <sys/user.h>
  38 #include <sys/proc.h>
  39 #include <sys/disp.h>
  40 #include <sys/buf.h>
  41 #include <sys/pathname.h>
  42 #include <sys/vfs.h>
  43 #include <sys/vnode.h>
  44 #include <sys/file.h>
  45 #include <sys/uio.h>
  46 #include <sys/conf.h>
  47 #include <sys/stat.h>
  48 #include <sys/mode.h>
  49 #include <sys/mkdev.h>
  50 #include <sys/ddi.h>
  51 
  52 #include <vm/page.h>
  53 
  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>
  60 
  61 #include <sys/statvfs.h>
  62 #include <sys/mount.h>
  63 #include <sys/swap.h>
  64 #include <sys/errno.h>
  65 #include <sys/debug.h>
  66 #include "fs/fs_subr.h"
  67 #include <sys/cmn_err.h>
  68 
  69 static void form_time(int, uchar_t *, struct timeval *);
  70 static void name_parse(int, uchar_t *, size_t, uchar_t *, int *,
  71     ulong_t *, int);
  72 
  73 /*
  74  *  Signature table for RRIP
  75  */
  76 ext_signature_t  rrip_signature_table[ ] = {
  77         { RRIP_CL,      rrip_child_link },
  78         { RRIP_NM,      rrip_name },
  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 },
  86         { NULL,         NULL }
  87 };
  88 
  89 
  90 /*
  91  * rrip_dev_nodes()
  92  *
  93  * sig_handler() for RRIP signature "PN"
  94  *
  95  * This function parses out the major and minor numbers from the "PN
  96  * " SUF.
  97  */
  98 uchar_t *
  99 rrip_dev_nodes(sig_args_t *sig_args_p)
 100 {
 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);
 104 
 105         sig_args_p->hdp->r_dev = makedevice(major_dev, minor_dev);
 106 
 107         return (pn_ptr + SUF_LEN(pn_ptr));
 108 }
 109 
 110 /*
 111  * rrip_file_attr()
 112  *
 113  * sig_handler() for RRIP signature "PX"
 114  *
 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,
 117  * and st_gid.
 118  */
 119 uchar_t *
 120 rrip_file_attr(sig_args_t *sig_args_p)
 121 {
 122         uchar_t *px_ptr = sig_args_p->SUF_ptr;
 123         struct hs_direntry *hdp    = sig_args_p->hdp;
 124 
 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);
 129 
 130         if (SUF_LEN(px_ptr) >= RRIP_PX_SIZE)
 131                 hdp->inode = (ino64_t)RRIP_INO(px_ptr);
 132         else
 133                 hdp->inode = 0;
 134 
 135         hdp->type = IFTOVT(hdp->mode);
 136 
 137         return (px_ptr + SUF_LEN(px_ptr));
 138 }
 139 
 140 /*
 141  * rrip_file_time()
 142  *
 143  * support function for rrip_file_time()
 144  *
 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.
 148  */
 149 static void
 150 form_time(int time_length, uchar_t *file_time, struct timeval *tvp)
 151 {
 152         if (time_length == ISO_DATE_LEN)
 153                 hs_parse_longdate(file_time, tvp);
 154         else
 155                 hs_parse_dirdate(file_time, tvp);
 156 
 157 }
 158 
 159 /*
 160  * rrip_file_time()
 161  *
 162  * sig_handler() for RRIP signature RRIP_TF
 163  *
 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.
 166  *
 167  * The function form_time is a support function only used in this
 168  * function.
 169  */
 170 uchar_t *
 171 rrip_file_time(sig_args_t *sig_args_p)
 172 {
 173         uchar_t *tf_ptr = sig_args_p->SUF_ptr;
 174 
 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);
 179         }
 180 
 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);
 184         }
 185 
 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);
 190         }
 191 
 192         return (tf_ptr + SUF_LEN(tf_ptr));
 193 }
 194 
 195 
 196 
 197 /*
 198  * name_parse()
 199  *
 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.
 202  *
 203  * The return value will be the NAME_CONTINUE or NAME_CHANGE value.
 204  *
 205  */
 206 static void
 207 name_parse(
 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 */
 215                                                 /* this value */
 216 {
 217         size_t  off;
 218         size_t  len;
 219 
 220         if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_ROOT))
 221                 dst[0] = 0;
 222 
 223         if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_CURRENT)) {
 224                 SUA_string = (uchar_t *)".";
 225                 SUA_string_len = 1;
 226         }
 227 
 228         if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_PARENT)) {
 229                 SUA_string = (uchar_t *)"..";
 230                 SUA_string_len = 2;
 231         }
 232 
 233         /*
 234          * XXX
 235          * For now, ignore the following flags and return.
 236          * have to figure out how to get host name in kernel.
 237          * Unsure if this even should be done.
 238          */
 239         if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_VOLROOT) ||
 240             IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_HOST)) {
 241                 cmn_err(CE_NOTE,
 242                         "VOLUME ROOT and NAME_HOST currently unsupported\n");
 243                 return;
 244         }
 245 
 246         /*
 247          * strlcat() has two nice properties:
 248          * - the size of the output buffer includes the trailing '\0'
 249          * - we pass "total size" not "remaining size"
 250          * It'd be the ideal candidate for this codeblock - make it:
 251          *
 252          *      strlcat(dst, SUA_string,
 253          *          MIN(dstsize, strlen(dst) + SUA_string_len + 1));
 254          *
 255          * Unfortunately, strlcat() cannot deal with input strings
 256          * that are not NULL-terminated - like SUA_string can be in
 257          * our case here. So we can't use it :(
 258          * Now strncat() doesn't work either - because it doesn't deal
 259          * with strings for which the 'potential NULL-termination' isn't
 260          * accessible - strncat(dst, NULL, 0) crashes although it copies
 261          * nothing in any case. If the SUA ends on a mapping boundary,
 262          * then telling strncat() to copy no more than the remaining bytes
 263          * in the buffer is of no avail if there's no NULL byte in them.
 264          *
 265          * Hence - binary copy. What are all these str* funcs for ??
 266          */
 267         dst_size--;     /* trailing '\0' */
 268 
 269         off = strlen((char *)dst);
 270         len = MIN(dst_size - off, SUA_string_len);
 271         bcopy((char *)SUA_string, (char *)(dst + off), len);
 272         dst[off + len] = '\0';
 273         *dst_lenp = strlen((char *)dst);
 274 
 275         if (IS_NAME_BIT_SET(rrip_flags, RRIP_NAME_CONTINUE))
 276                 SET_NAME_BIT(*(name_flags_p), RRIP_NAME_CONTINUE);
 277         else
 278                 SET_NAME_BIT(*(name_flags_p), RRIP_NAME_CHANGE);
 279 
 280 }
 281 
 282 /*
 283  * rrip_name()
 284  *
 285  * sig_handler() for RRIP signature RRIP_NM
 286  *
 287  * This function handles the name of the current file.  It is case
 288  * sensitive to whatever was put into the field and does NO
 289  * translation. It will take whatever characters were in the field.
 290  *
 291  * Because the flags effect the way the name is parsed the same way
 292  * that the sym_link component parsing is done, we will use the same
 293  * function to do the actual parsing.
 294  */
 295 uchar_t  *
 296 rrip_name(sig_args_t *sig_args_p)
 297 {
 298         uchar_t *nm_ptr = sig_args_p->SUF_ptr;
 299 
 300         if ((sig_args_p->name_p == (uchar_t *)NULL) ||
 301             (sig_args_p->name_len_p == (int *)NULL))
 302                 goto end;
 303         /*
 304          * If we have a "." or ".." directory, we should not look for
 305          * an alternate name
 306          */
 307         if (HDE_NAME_LEN(sig_args_p->dirp) == 1) {
 308                 if (*((char *)HDE_name(sig_args_p->dirp)) == '\0') {
 309                         (void) strcpy((char *)sig_args_p->name_p, ".");
 310                         *sig_args_p->name_len_p = 1;
 311                         goto end;
 312                 } else if (*((char *)HDE_name(sig_args_p->dirp)) == '\1') {
 313                         (void) strcpy((char *)sig_args_p->name_p, "..");
 314                         *sig_args_p->name_len_p = 2;
 315                         goto end;
 316                 }
 317         }
 318 
 319         name_parse((int)RRIP_NAME_FLAGS(nm_ptr), RRIP_name(nm_ptr),
 320             (size_t)RRIP_NAME_LEN(nm_ptr), sig_args_p->name_p,
 321             sig_args_p->name_len_p, &(sig_args_p->name_flags),
 322             MAXNAMELEN);
 323 
 324 end:
 325         return (nm_ptr + SUF_LEN(nm_ptr));
 326 }
 327 
 328 
 329 /*
 330  * rrip_sym_link()
 331  *
 332  * sig_handler() for RRIP signature RRIP_SL
 333  *
 334  * creates a symlink buffer to simulate sym_links.
 335  */
 336 uchar_t *
 337 rrip_sym_link(sig_args_t *sig_args_p)
 338 {
 339         uchar_t *sl_ptr = sig_args_p->SUF_ptr;
 340         uchar_t *comp_ptr;
 341         char    *tmp_sym_link;
 342         struct hs_direntry *hdp = sig_args_p->hdp;
 343         int     sym_link_len;
 344         char    *sym_link;
 345 
 346         if (hdp->type != VLNK)
 347                 goto end;
 348 
 349         /*
 350          * If the sym link has already been created, don't recreate it
 351          */
 352         if (IS_NAME_BIT_SET(sig_args_p->name_flags, RRIP_SYM_LINK_COMPLETE))
 353                 goto end;
 354 
 355         sym_link = kmem_alloc(MAXPATHLEN + 1, KM_SLEEP);
 356 
 357         /*
 358          * If there is an original string put it into sym_link[], otherwise
 359          * initialize sym_link[] to the empty string.
 360          */
 361         if (hdp->sym_link != (char *)NULL) {
 362                 sym_link_len = (int)strlen(strcpy(sym_link, hdp->sym_link));
 363         } else {
 364                 sym_link[0] = '\0';
 365                 sym_link_len = 0;
 366         }
 367 
 368         /* for all components */
 369         for (comp_ptr = RRIP_sl_comp(sl_ptr);
 370             comp_ptr < (sl_ptr + SUF_LEN(sl_ptr));
 371             comp_ptr += RRIP_COMP_LEN(comp_ptr)) {
 372 
 373                 name_parse((int)RRIP_COMP_FLAGS(comp_ptr),
 374                     RRIP_comp(comp_ptr),
 375                     (size_t)RRIP_COMP_NAME_LEN(comp_ptr), (uchar_t *)sym_link,
 376                     &sym_link_len, &(sig_args_p->name_flags),
 377                     MAXPATHLEN);
 378 
 379                 /*
 380                  * If the component is continued don't put a '/' in
 381                  * the pathname, but do NULL terminate it.
 382                  */
 383                 if (IS_NAME_BIT_SET(RRIP_COMP_FLAGS(comp_ptr),
 384                     RRIP_NAME_CONTINUE)) {
 385                         sym_link[sym_link_len] = '\0';
 386                 } else {
 387                         sym_link[sym_link_len] = '/';
 388                         sym_link[sym_link_len + 1] = '\0';
 389 
 390                         /* add 1 to sym_link_len for '/' */
 391                         sym_link_len++;
 392                 }
 393 
 394         }
 395 
 396         /*
 397          * If we reached the end of the symbolic link, take out the
 398          * last slash, but don't change ROOT "/" to an empty string.
 399          */
 400         if (!IS_NAME_BIT_SET(RRIP_SL_FLAGS(sl_ptr), RRIP_NAME_CONTINUE) &&
 401             sym_link_len > 1 && sym_link[sym_link_len - 1] == '/')
 402                 sym_link[--sym_link_len] = '\0';
 403 
 404         /*
 405          * if no memory has been allocated, get some, otherwise, append
 406          * to the current allocation
 407          */
 408 
 409         tmp_sym_link = kmem_alloc(SYM_LINK_LEN(sym_link), KM_SLEEP);
 410 
 411         (void) strcpy(tmp_sym_link, sym_link);
 412 
 413         if (hdp->sym_link != (char *)NULL)
 414                 kmem_free(hdp->sym_link, (size_t)(hdp->ext_size + 1));
 415 
 416         hdp->sym_link = (char *)&tmp_sym_link[0];
 417         /* the size of a symlink is its length */
 418         hdp->ext_size = (uint_t)strlen(tmp_sym_link);
 419 
 420         if (!IS_NAME_BIT_SET(RRIP_SL_FLAGS(sl_ptr), RRIP_NAME_CONTINUE)) {
 421                 /* reached the end of the symbolic link */
 422                 SET_NAME_BIT(sig_args_p->name_flags, RRIP_SYM_LINK_COMPLETE);
 423         }
 424 
 425         kmem_free(sym_link, MAXPATHLEN + 1);
 426 end:
 427         return (sl_ptr + SUF_LEN(sl_ptr));
 428 }
 429 
 430 /*
 431  * rrip_namecopy()
 432  *
 433  * This function will copy the rrip name to the "to" buffer, if it
 434  * exists.
 435  *
 436  * XXX -  We should speed this up by implementing the search in
 437  * parse_sua().  It works right now, so I don't want to mess with it.
 438  */
 439 int
 440 rrip_namecopy(
 441         char    *from,                  /* name to copy */
 442         char    *to,                    /* string to copy "from" to */
 443         char    *tmp_name,              /* temp storage for original name */
 444         uchar_t *dirp,                  /* directory entry pointer */
 445         uint_t  last_offset,            /* last index into current dir block */
 446         struct  hsfs *fsp,              /* filesystem pointer */
 447         struct  hs_direntry *hdp)       /* directory entry pointer to put */
 448                                         /* all that good info in */
 449 {
 450         int     size = 0;
 451         int     change_flag = 0;
 452         int     ret_val;
 453 
 454         if ((to == (char *)NULL) ||
 455             (from == (char *)NULL) ||
 456             (dirp == (uchar_t *)NULL)) {
 457                 return (0);
 458         }
 459 
 460         /* special handling for '.' and '..' */
 461 
 462         if (HDE_NAME_LEN(dirp) == 1) {
 463                 if (*((char *)HDE_name(dirp)) == '\0') {
 464                         (void) strcpy(to, ".");
 465                         return (1);
 466                 } else if (*((char *)HDE_name(dirp)) == '\1') {
 467                         (void) strcpy(to, "..");
 468                         return (2);
 469                 }
 470         }
 471 
 472 
 473         ret_val = parse_sua((uchar_t *)to, &size, &change_flag,
 474                         dirp, last_offset,
 475                         hdp, fsp, (uchar_t *)NULL, NULL);
 476 
 477         if (IS_NAME_BIT_SET(change_flag, RRIP_NAME_CHANGE) && !ret_val)
 478                 return (size);
 479 
 480         /*
 481          * Well, the name was not found
 482          *
 483          * make rripname an upper case "nm" (to), so that
 484          * we can compare it the current HDE_DIR_NAME()
 485          * without nuking the original "nm", for future case
 486          * sensitive name comparing
 487          */
 488         (void) strcpy(tmp_name, from);          /* keep original */
 489         size = hs_uppercase_copy(tmp_name, from, (int)strlen(from));
 490 
 491         return (-1);
 492 }
 493 
 494 
 495 
 496 /*
 497  * rrip_reloc_dir()
 498  *
 499  * This function is fairly bogus.  All it does is cause a failure of
 500  * the hs_parsedir, so that no vnode will be made for it and
 501  * essentially, the directory will no longer be seen.  This is part
 502  * of the directory hierarchy mess, where the relocated directory will
 503  * be hidden as far as ISO 9660 is concerned.  When we hit the child
 504  * link "CL" SUF, then we will read the new directory.
 505  */
 506 uchar_t *
 507 rrip_reloc_dir(sig_args_t *sig_args_p)
 508 {
 509         uchar_t *re_ptr = sig_args_p->SUF_ptr;
 510 
 511         sig_args_p->flags = RELOC_DIR;
 512 
 513         return (re_ptr + SUF_LEN(re_ptr));
 514 }
 515 
 516 
 517 
 518 /*
 519  * rrip_child_link()
 520  *
 521  * This is the child link part of the directory hierarchy stuff and
 522  * this does not really do much anyway.  All it does is read the
 523  * directory entry that the child link SUF contains.  All should be
 524  * fine then.
 525  */
 526 uchar_t *
 527 rrip_child_link(sig_args_t *sig_args_p)
 528 {
 529         uchar_t *cl_ptr = sig_args_p->SUF_ptr;
 530 
 531         sig_args_p->hdp->ext_lbn = RRIP_CHILD_LBN(cl_ptr);
 532 
 533         hs_filldirent(sig_args_p->fsp->hsfs_rootvp, sig_args_p->hdp);
 534 
 535         sig_args_p->flags = 0;
 536 
 537         return (cl_ptr + SUF_LEN(cl_ptr));
 538 }
 539 
 540 
 541 /*
 542  * rrip_parent_link()
 543  *
 544  * This is the parent link part of the directory hierarchy stuff and
 545  * this does not really do much anyway.  All it does is read the
 546  * directory entry that the parent link SUF contains.  All should be
 547  * fine then.
 548  */
 549 uchar_t *
 550 rrip_parent_link(sig_args_t *sig_args_p)
 551 {
 552         uchar_t *pl_ptr = sig_args_p->SUF_ptr;
 553 
 554         sig_args_p->hdp->ext_lbn = RRIP_PARENT_LBN(pl_ptr);
 555 
 556         hs_filldirent(sig_args_p->fsp->hsfs_rootvp, sig_args_p->hdp);
 557 
 558         sig_args_p->flags = 0;
 559 
 560         return (pl_ptr + SUF_LEN(pl_ptr));
 561 }
 562 
 563 
 564 /*
 565  * rrip_rock_ridge()
 566  *
 567  * This function is supposed to aid in speed of the filesystem.
 568  *
 569  * XXX - It is only here as a place holder so far.
 570  */
 571 uchar_t *
 572 rrip_rock_ridge(sig_args_t *sig_args_p)
 573 {
 574         uchar_t *rr_ptr = sig_args_p->SUF_ptr;
 575 
 576         return (rr_ptr + SUF_LEN(rr_ptr));
 577 }