1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Miscellaneous support subroutines for High Sierra filesystem 24*7c478bd9Sstevel@tonic-gate * 25*7c478bd9Sstevel@tonic-gate * Copyright (c) 1990,2000,2001 by Sun Microsystems, Inc. 26*7c478bd9Sstevel@tonic-gate * All rights reserved. 27*7c478bd9Sstevel@tonic-gate */ 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 30*7c478bd9Sstevel@tonic-gate 31*7c478bd9Sstevel@tonic-gate #include <sys/types.h> 32*7c478bd9Sstevel@tonic-gate #include <sys/param.h> 33*7c478bd9Sstevel@tonic-gate #include <sys/time.h> 34*7c478bd9Sstevel@tonic-gate #include <sys/cmn_err.h> 35*7c478bd9Sstevel@tonic-gate #include <sys/systm.h> 36*7c478bd9Sstevel@tonic-gate #include <sys/sysmacros.h> 37*7c478bd9Sstevel@tonic-gate #include <sys/buf.h> 38*7c478bd9Sstevel@tonic-gate #include <sys/conf.h> 39*7c478bd9Sstevel@tonic-gate #include <sys/user.h> 40*7c478bd9Sstevel@tonic-gate #include <sys/vfs.h> 41*7c478bd9Sstevel@tonic-gate #include <sys/vnode.h> 42*7c478bd9Sstevel@tonic-gate #include <sys/proc.h> 43*7c478bd9Sstevel@tonic-gate #include <sys/debug.h> 44*7c478bd9Sstevel@tonic-gate #include <sys/kmem.h> 45*7c478bd9Sstevel@tonic-gate #include <sys/uio.h> 46*7c478bd9Sstevel@tonic-gate #include <vm/hat.h> 47*7c478bd9Sstevel@tonic-gate #include <vm/as.h> 48*7c478bd9Sstevel@tonic-gate #include <vm/seg.h> 49*7c478bd9Sstevel@tonic-gate #include <vm/page.h> 50*7c478bd9Sstevel@tonic-gate #include <vm/pvn.h> 51*7c478bd9Sstevel@tonic-gate #include <vm/seg_map.h> 52*7c478bd9Sstevel@tonic-gate #include <sys/swap.h> 53*7c478bd9Sstevel@tonic-gate #include <vm/seg_kmem.h> 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_spec.h> 56*7c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_node.h> 57*7c478bd9Sstevel@tonic-gate #include <sys/fs/hsfs_impl.h> 58*7c478bd9Sstevel@tonic-gate 59*7c478bd9Sstevel@tonic-gate #define THE_EPOCH 1970 60*7c478bd9Sstevel@tonic-gate #define END_OF_TIME 2099 61*7c478bd9Sstevel@tonic-gate 62*7c478bd9Sstevel@tonic-gate #ifdef __STDC__ 63*7c478bd9Sstevel@tonic-gate static time_t hs_date_to_gmtime(int year, int mon, int day, int gmtoff); 64*7c478bd9Sstevel@tonic-gate #else 65*7c478bd9Sstevel@tonic-gate static time_t hs_date_to_gmtime(); 66*7c478bd9Sstevel@tonic-gate #endif 67*7c478bd9Sstevel@tonic-gate 68*7c478bd9Sstevel@tonic-gate /* 69*7c478bd9Sstevel@tonic-gate * Table used in logging non-fatal errors which should be recorded 70*7c478bd9Sstevel@tonic-gate * once per mount. Indexed by HSFS_ERR values (defined in hsfs_node.h). 71*7c478bd9Sstevel@tonic-gate */ 72*7c478bd9Sstevel@tonic-gate struct hsfs_error { 73*7c478bd9Sstevel@tonic-gate char *hdr_text; /* msg prefix: general error type */ 74*7c478bd9Sstevel@tonic-gate /* must contain %s for mnt pt */ 75*7c478bd9Sstevel@tonic-gate char *err_text; /* specific error message */ 76*7c478bd9Sstevel@tonic-gate uchar_t multiple; /* > 1 such error per fs possible? */ 77*7c478bd9Sstevel@tonic-gate uchar_t n_printf_args; /* if err_text printf-like, # addtl args */ 78*7c478bd9Sstevel@tonic-gate } hsfs_error[] = { 79*7c478bd9Sstevel@tonic-gate /* HSFS_ERR_TRAILING_JUNK */ 80*7c478bd9Sstevel@tonic-gate "hsfs: Warning: the file system mounted on %s\n" 81*7c478bd9Sstevel@tonic-gate "does not conform to the ISO-9660 specification:", 82*7c478bd9Sstevel@tonic-gate " trailing blanks or null characters in file or directory name.\n", 83*7c478bd9Sstevel@tonic-gate 1, 0, 84*7c478bd9Sstevel@tonic-gate /* HSFS_ERR_LOWER_CASE_NM */ 85*7c478bd9Sstevel@tonic-gate "hsfs: Warning: the file system mounted on %s\n" 86*7c478bd9Sstevel@tonic-gate "does not conform to the ISO-9660 specification: ", 87*7c478bd9Sstevel@tonic-gate " lower case characters in file or directory name.\n", 88*7c478bd9Sstevel@tonic-gate 1, 0, 89*7c478bd9Sstevel@tonic-gate /* HSFS_ERR_BAD_ROOT_DIR */ 90*7c478bd9Sstevel@tonic-gate "hsfs: Warning: the file system mounted on %s\n" 91*7c478bd9Sstevel@tonic-gate "does not conform to the ISO-9660 specification:", 92*7c478bd9Sstevel@tonic-gate " invalid root directory.\n", 93*7c478bd9Sstevel@tonic-gate 0, 0, 94*7c478bd9Sstevel@tonic-gate /* HSFS_ERR_UNSUP_TYPE */ 95*7c478bd9Sstevel@tonic-gate "hsfs: Warning: the file system mounted on %s\n" 96*7c478bd9Sstevel@tonic-gate "contains a file or directory with an unsupported type:", 97*7c478bd9Sstevel@tonic-gate " 0x%x.\n", 98*7c478bd9Sstevel@tonic-gate 1, 1, 99*7c478bd9Sstevel@tonic-gate /* HSFS_ERR_BAD_FILE_LEN */ 100*7c478bd9Sstevel@tonic-gate "hsfs: Warning: file system mounted on %s \n" 101*7c478bd9Sstevel@tonic-gate "does not conform to the ISO-9660 specification:", 102*7c478bd9Sstevel@tonic-gate "file len greater than max allowed\n", 103*7c478bd9Sstevel@tonic-gate 1, 0, 104*7c478bd9Sstevel@tonic-gate }; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate 107*7c478bd9Sstevel@tonic-gate 108*7c478bd9Sstevel@tonic-gate /* 109*7c478bd9Sstevel@tonic-gate * hs_parse_dirdate 110*7c478bd9Sstevel@tonic-gate * 111*7c478bd9Sstevel@tonic-gate * Parse the short 'directory-format' date into a Unix timeval. 112*7c478bd9Sstevel@tonic-gate * This is the date format used in Directory Entries. 113*7c478bd9Sstevel@tonic-gate * 114*7c478bd9Sstevel@tonic-gate * If the date is not representable, make something up. 115*7c478bd9Sstevel@tonic-gate */ 116*7c478bd9Sstevel@tonic-gate void 117*7c478bd9Sstevel@tonic-gate hs_parse_dirdate(dp, tvp) 118*7c478bd9Sstevel@tonic-gate uchar_t *dp; 119*7c478bd9Sstevel@tonic-gate struct timeval *tvp; 120*7c478bd9Sstevel@tonic-gate { 121*7c478bd9Sstevel@tonic-gate int year, month, day, hour, minute, sec, gmtoff; 122*7c478bd9Sstevel@tonic-gate 123*7c478bd9Sstevel@tonic-gate year = HDE_DATE_YEAR(dp); 124*7c478bd9Sstevel@tonic-gate month = HDE_DATE_MONTH(dp); 125*7c478bd9Sstevel@tonic-gate day = HDE_DATE_DAY(dp); 126*7c478bd9Sstevel@tonic-gate hour = HDE_DATE_HOUR(dp); 127*7c478bd9Sstevel@tonic-gate minute = HDE_DATE_MIN(dp); 128*7c478bd9Sstevel@tonic-gate sec = HDE_DATE_SEC(dp); 129*7c478bd9Sstevel@tonic-gate gmtoff = HDE_DATE_GMTOFF(dp); 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate tvp->tv_usec = 0; 132*7c478bd9Sstevel@tonic-gate if (year < THE_EPOCH) { 133*7c478bd9Sstevel@tonic-gate tvp->tv_sec = 0; 134*7c478bd9Sstevel@tonic-gate } else { 135*7c478bd9Sstevel@tonic-gate tvp->tv_sec = hs_date_to_gmtime(year, month, day, gmtoff); 136*7c478bd9Sstevel@tonic-gate if (tvp->tv_sec != -1) { 137*7c478bd9Sstevel@tonic-gate tvp->tv_sec += ((hour * 60) + minute) * 60 + sec; 138*7c478bd9Sstevel@tonic-gate } 139*7c478bd9Sstevel@tonic-gate } 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate return; 142*7c478bd9Sstevel@tonic-gate 143*7c478bd9Sstevel@tonic-gate } 144*7c478bd9Sstevel@tonic-gate 145*7c478bd9Sstevel@tonic-gate /* 146*7c478bd9Sstevel@tonic-gate * hs_parse_longdate 147*7c478bd9Sstevel@tonic-gate * 148*7c478bd9Sstevel@tonic-gate * Parse the long 'user-oriented' date into a Unix timeval. 149*7c478bd9Sstevel@tonic-gate * This is the date format used in the Volume Descriptor. 150*7c478bd9Sstevel@tonic-gate * 151*7c478bd9Sstevel@tonic-gate * If the date is not representable, make something up. 152*7c478bd9Sstevel@tonic-gate */ 153*7c478bd9Sstevel@tonic-gate void 154*7c478bd9Sstevel@tonic-gate hs_parse_longdate(dp, tvp) 155*7c478bd9Sstevel@tonic-gate uchar_t *dp; 156*7c478bd9Sstevel@tonic-gate struct timeval *tvp; 157*7c478bd9Sstevel@tonic-gate { 158*7c478bd9Sstevel@tonic-gate int year, month, day, hour, minute, sec, gmtoff; 159*7c478bd9Sstevel@tonic-gate 160*7c478bd9Sstevel@tonic-gate year = HSV_DATE_YEAR(dp); 161*7c478bd9Sstevel@tonic-gate month = HSV_DATE_MONTH(dp); 162*7c478bd9Sstevel@tonic-gate day = HSV_DATE_DAY(dp); 163*7c478bd9Sstevel@tonic-gate hour = HSV_DATE_HOUR(dp); 164*7c478bd9Sstevel@tonic-gate minute = HSV_DATE_MIN(dp); 165*7c478bd9Sstevel@tonic-gate sec = HSV_DATE_SEC(dp); 166*7c478bd9Sstevel@tonic-gate gmtoff = HSV_DATE_GMTOFF(dp); 167*7c478bd9Sstevel@tonic-gate 168*7c478bd9Sstevel@tonic-gate tvp->tv_usec = 0; 169*7c478bd9Sstevel@tonic-gate if (year < THE_EPOCH) { 170*7c478bd9Sstevel@tonic-gate tvp->tv_sec = 0; 171*7c478bd9Sstevel@tonic-gate } else { 172*7c478bd9Sstevel@tonic-gate tvp->tv_sec = hs_date_to_gmtime(year, month, day, gmtoff); 173*7c478bd9Sstevel@tonic-gate if (tvp->tv_sec != -1) { 174*7c478bd9Sstevel@tonic-gate tvp->tv_sec += ((hour * 60) + minute) * 60 + sec; 175*7c478bd9Sstevel@tonic-gate tvp->tv_usec = HSV_DATE_HSEC(dp) * 10000; 176*7c478bd9Sstevel@tonic-gate } 177*7c478bd9Sstevel@tonic-gate } 178*7c478bd9Sstevel@tonic-gate 179*7c478bd9Sstevel@tonic-gate } 180*7c478bd9Sstevel@tonic-gate 181*7c478bd9Sstevel@tonic-gate /* cumulative number of seconds per month, non-leap and leap-year versions */ 182*7c478bd9Sstevel@tonic-gate static time_t cum_sec[] = { 183*7c478bd9Sstevel@tonic-gate 0x0, 0x28de80, 0x4dc880, 0x76a700, 0x9e3400, 0xc71280, 184*7c478bd9Sstevel@tonic-gate 0xee9f80, 0x1177e00, 0x1405c80, 0x167e980, 0x190c800, 0x1b85500 185*7c478bd9Sstevel@tonic-gate }; 186*7c478bd9Sstevel@tonic-gate static time_t cum_sec_leap[] = { 187*7c478bd9Sstevel@tonic-gate 0x0, 0x28de80, 0x4f1a00, 0x77f880, 0x9f8580, 0xc86400, 188*7c478bd9Sstevel@tonic-gate 0xeff100, 0x118cf80, 0x141ae00, 0x1693b00, 0x1921980, 0x1b9a680 189*7c478bd9Sstevel@tonic-gate }; 190*7c478bd9Sstevel@tonic-gate #define SEC_PER_DAY 0x15180 191*7c478bd9Sstevel@tonic-gate #define SEC_PER_YEAR 0x1e13380 192*7c478bd9Sstevel@tonic-gate 193*7c478bd9Sstevel@tonic-gate /* 194*7c478bd9Sstevel@tonic-gate * hs_date_to_gmtime 195*7c478bd9Sstevel@tonic-gate * 196*7c478bd9Sstevel@tonic-gate * Convert year(1970-2099)/month(1-12)/day(1-31) to seconds-since-1970/1/1. 197*7c478bd9Sstevel@tonic-gate * 198*7c478bd9Sstevel@tonic-gate * Returns -1 if the date is out of range. 199*7c478bd9Sstevel@tonic-gate */ 200*7c478bd9Sstevel@tonic-gate static time_t 201*7c478bd9Sstevel@tonic-gate hs_date_to_gmtime(year, mon, day, gmtoff) 202*7c478bd9Sstevel@tonic-gate int year; 203*7c478bd9Sstevel@tonic-gate int mon; 204*7c478bd9Sstevel@tonic-gate int day; 205*7c478bd9Sstevel@tonic-gate int gmtoff; 206*7c478bd9Sstevel@tonic-gate { 207*7c478bd9Sstevel@tonic-gate time_t sum; 208*7c478bd9Sstevel@tonic-gate time_t *cp; 209*7c478bd9Sstevel@tonic-gate int y; 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate if ((year < THE_EPOCH) || (year > END_OF_TIME) || 212*7c478bd9Sstevel@tonic-gate (mon < 1) || (mon > 12) || 213*7c478bd9Sstevel@tonic-gate (day < 1) || (day > 31)) 214*7c478bd9Sstevel@tonic-gate return (-1); 215*7c478bd9Sstevel@tonic-gate 216*7c478bd9Sstevel@tonic-gate /* 217*7c478bd9Sstevel@tonic-gate * Figure seconds until this year and correct for leap years. 218*7c478bd9Sstevel@tonic-gate * Note: 2000 is a leap year but not 2100. 219*7c478bd9Sstevel@tonic-gate */ 220*7c478bd9Sstevel@tonic-gate y = year - THE_EPOCH; 221*7c478bd9Sstevel@tonic-gate sum = y * SEC_PER_YEAR; 222*7c478bd9Sstevel@tonic-gate sum += ((y + 1) / 4) * SEC_PER_DAY; 223*7c478bd9Sstevel@tonic-gate /* 224*7c478bd9Sstevel@tonic-gate * Point to the correct table for this year and 225*7c478bd9Sstevel@tonic-gate * add in seconds until this month. 226*7c478bd9Sstevel@tonic-gate */ 227*7c478bd9Sstevel@tonic-gate cp = ((y + 2) % 4) ? cum_sec : cum_sec_leap; 228*7c478bd9Sstevel@tonic-gate sum += cp[mon - 1]; 229*7c478bd9Sstevel@tonic-gate /* 230*7c478bd9Sstevel@tonic-gate * Add in seconds until 0:00 of this day. 231*7c478bd9Sstevel@tonic-gate * (days-per-month validation is not done here) 232*7c478bd9Sstevel@tonic-gate */ 233*7c478bd9Sstevel@tonic-gate sum += (day - 1) * SEC_PER_DAY; 234*7c478bd9Sstevel@tonic-gate sum -= (gmtoff * 15 * 60); 235*7c478bd9Sstevel@tonic-gate return (sum); 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate /* 239*7c478bd9Sstevel@tonic-gate * Indicate whether the directory is valid. 240*7c478bd9Sstevel@tonic-gate */ 241*7c478bd9Sstevel@tonic-gate 242*7c478bd9Sstevel@tonic-gate int 243*7c478bd9Sstevel@tonic-gate hsfs_valid_dir(hd) 244*7c478bd9Sstevel@tonic-gate struct hs_direntry *hd; 245*7c478bd9Sstevel@tonic-gate { 246*7c478bd9Sstevel@tonic-gate /* 247*7c478bd9Sstevel@tonic-gate * check to see if this directory is not marked as a directory. 248*7c478bd9Sstevel@tonic-gate * check to see if data length is zero. 249*7c478bd9Sstevel@tonic-gate */ 250*7c478bd9Sstevel@tonic-gate 251*7c478bd9Sstevel@tonic-gate if (hd->ext_size == 0) 252*7c478bd9Sstevel@tonic-gate return (0); 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate if (hd->type != VDIR) 255*7c478bd9Sstevel@tonic-gate return (0); 256*7c478bd9Sstevel@tonic-gate 257*7c478bd9Sstevel@tonic-gate return (1); 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate 261*7c478bd9Sstevel@tonic-gate 262*7c478bd9Sstevel@tonic-gate /* 263*7c478bd9Sstevel@tonic-gate * If we haven't complained about this error type yet, do. 264*7c478bd9Sstevel@tonic-gate */ 265*7c478bd9Sstevel@tonic-gate void 266*7c478bd9Sstevel@tonic-gate hs_log_bogus_disk_warning(fsp, errtype, data) 267*7c478bd9Sstevel@tonic-gate struct hsfs *fsp; 268*7c478bd9Sstevel@tonic-gate int errtype; 269*7c478bd9Sstevel@tonic-gate uint_t data; 270*7c478bd9Sstevel@tonic-gate { 271*7c478bd9Sstevel@tonic-gate 272*7c478bd9Sstevel@tonic-gate if (fsp->hsfs_err_flags & (1 << errtype)) 273*7c478bd9Sstevel@tonic-gate return; /* already complained */ 274*7c478bd9Sstevel@tonic-gate 275*7c478bd9Sstevel@tonic-gate cmn_err(CE_NOTE, hsfs_error[errtype].hdr_text, 276*7c478bd9Sstevel@tonic-gate fsp->hsfs_fsmnt); 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate switch (hsfs_error[errtype].n_printf_args) { 279*7c478bd9Sstevel@tonic-gate case 0: 280*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, hsfs_error[errtype].err_text); 281*7c478bd9Sstevel@tonic-gate break; 282*7c478bd9Sstevel@tonic-gate case 1: 283*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, hsfs_error[errtype].err_text, data); 284*7c478bd9Sstevel@tonic-gate break; 285*7c478bd9Sstevel@tonic-gate default: 286*7c478bd9Sstevel@tonic-gate /* don't currently handle more than 1 arg */ 287*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "unknown problem; internal error.\n"); 288*7c478bd9Sstevel@tonic-gate } 289*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 290*7c478bd9Sstevel@tonic-gate "Due to this error, the file system may not be correctly interpreted.\n"); 291*7c478bd9Sstevel@tonic-gate if (hsfs_error[errtype].multiple) 292*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, 293*7c478bd9Sstevel@tonic-gate "Other such errors in this file system will be silently ignored.\n\n"); 294*7c478bd9Sstevel@tonic-gate else 295*7c478bd9Sstevel@tonic-gate cmn_err(CE_CONT, "\n"); 296*7c478bd9Sstevel@tonic-gate 297*7c478bd9Sstevel@tonic-gate fsp->hsfs_err_flags |= (1 << errtype); 298*7c478bd9Sstevel@tonic-gate } 299