1*11963SAfshin.Ardakani@Sun.COM /* 2*11963SAfshin.Ardakani@Sun.COM * CDDL HEADER START 3*11963SAfshin.Ardakani@Sun.COM * 4*11963SAfshin.Ardakani@Sun.COM * The contents of this file are subject to the terms of the 5*11963SAfshin.Ardakani@Sun.COM * Common Development and Distribution License (the "License"). 6*11963SAfshin.Ardakani@Sun.COM * You may not use this file except in compliance with the License. 7*11963SAfshin.Ardakani@Sun.COM * 8*11963SAfshin.Ardakani@Sun.COM * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9*11963SAfshin.Ardakani@Sun.COM * or http://www.opensolaris.org/os/licensing. 10*11963SAfshin.Ardakani@Sun.COM * See the License for the specific language governing permissions 11*11963SAfshin.Ardakani@Sun.COM * and limitations under the License. 12*11963SAfshin.Ardakani@Sun.COM * 13*11963SAfshin.Ardakani@Sun.COM * When distributing Covered Code, include this CDDL HEADER in each 14*11963SAfshin.Ardakani@Sun.COM * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15*11963SAfshin.Ardakani@Sun.COM * If applicable, add the following below this CDDL HEADER, with the 16*11963SAfshin.Ardakani@Sun.COM * fields enclosed by brackets "[]" replaced with your own identifying 17*11963SAfshin.Ardakani@Sun.COM * information: Portions Copyright [yyyy] [name of copyright owner] 18*11963SAfshin.Ardakani@Sun.COM * 19*11963SAfshin.Ardakani@Sun.COM * CDDL HEADER END 20*11963SAfshin.Ardakani@Sun.COM */ 21*11963SAfshin.Ardakani@Sun.COM /* 22*11963SAfshin.Ardakani@Sun.COM * Copyright 2010 Sun Microsystems, Inc. All rights reserved. 23*11963SAfshin.Ardakani@Sun.COM * Use is subject to license terms. 24*11963SAfshin.Ardakani@Sun.COM */ 25*11963SAfshin.Ardakani@Sun.COM 26*11963SAfshin.Ardakani@Sun.COM #include <sys/param.h> 27*11963SAfshin.Ardakani@Sun.COM #include <sys/types.h> 28*11963SAfshin.Ardakani@Sun.COM #include <sys/tzfile.h> 29*11963SAfshin.Ardakani@Sun.COM #include <sys/atomic.h> 30*11963SAfshin.Ardakani@Sun.COM #include <sys/kidmap.h> 31*11963SAfshin.Ardakani@Sun.COM #include <sys/time.h> 32*11963SAfshin.Ardakani@Sun.COM #include <sys/cpuvar.h> 33*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_kproto.h> 34*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_fsops.h> 35*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smbinfo.h> 36*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_xdr.h> 37*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_vops.h> 38*11963SAfshin.Ardakani@Sun.COM #include <smbsrv/smb_idmap.h> 39*11963SAfshin.Ardakani@Sun.COM 40*11963SAfshin.Ardakani@Sun.COM #include <sys/sid.h> 41*11963SAfshin.Ardakani@Sun.COM #include <sys/priv_names.h> 42*11963SAfshin.Ardakani@Sun.COM 43*11963SAfshin.Ardakani@Sun.COM static kmem_cache_t *smb_dtor_cache; 44*11963SAfshin.Ardakani@Sun.COM static boolean_t smb_llist_initialized = B_FALSE; 45*11963SAfshin.Ardakani@Sun.COM 46*11963SAfshin.Ardakani@Sun.COM static void smb_llist_flush(smb_llist_t *); 47*11963SAfshin.Ardakani@Sun.COM static boolean_t smb_thread_continue_timedwait_locked(smb_thread_t *, int); 48*11963SAfshin.Ardakani@Sun.COM 49*11963SAfshin.Ardakani@Sun.COM time_t tzh_leapcnt = 0; 50*11963SAfshin.Ardakani@Sun.COM 51*11963SAfshin.Ardakani@Sun.COM struct tm 52*11963SAfshin.Ardakani@Sun.COM *smb_gmtime_r(time_t *clock, struct tm *result); 53*11963SAfshin.Ardakani@Sun.COM 54*11963SAfshin.Ardakani@Sun.COM time_t 55*11963SAfshin.Ardakani@Sun.COM smb_timegm(struct tm *tm); 56*11963SAfshin.Ardakani@Sun.COM 57*11963SAfshin.Ardakani@Sun.COM struct tm { 58*11963SAfshin.Ardakani@Sun.COM int tm_sec; 59*11963SAfshin.Ardakani@Sun.COM int tm_min; 60*11963SAfshin.Ardakani@Sun.COM int tm_hour; 61*11963SAfshin.Ardakani@Sun.COM int tm_mday; 62*11963SAfshin.Ardakani@Sun.COM int tm_mon; 63*11963SAfshin.Ardakani@Sun.COM int tm_year; 64*11963SAfshin.Ardakani@Sun.COM int tm_wday; 65*11963SAfshin.Ardakani@Sun.COM int tm_yday; 66*11963SAfshin.Ardakani@Sun.COM int tm_isdst; 67*11963SAfshin.Ardakani@Sun.COM }; 68*11963SAfshin.Ardakani@Sun.COM 69*11963SAfshin.Ardakani@Sun.COM static int days_in_month[] = { 70*11963SAfshin.Ardakani@Sun.COM 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 71*11963SAfshin.Ardakani@Sun.COM }; 72*11963SAfshin.Ardakani@Sun.COM 73*11963SAfshin.Ardakani@Sun.COM int 74*11963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_strlen(struct smb_request *sr, char *str) 75*11963SAfshin.Ardakani@Sun.COM { 76*11963SAfshin.Ardakani@Sun.COM if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 77*11963SAfshin.Ardakani@Sun.COM return (smb_wcequiv_strlen(str)); 78*11963SAfshin.Ardakani@Sun.COM return (strlen(str)); 79*11963SAfshin.Ardakani@Sun.COM } 80*11963SAfshin.Ardakani@Sun.COM 81*11963SAfshin.Ardakani@Sun.COM int 82*11963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_strlen_null(struct smb_request *sr, char *str) 83*11963SAfshin.Ardakani@Sun.COM { 84*11963SAfshin.Ardakani@Sun.COM if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 85*11963SAfshin.Ardakani@Sun.COM return (smb_wcequiv_strlen(str) + 2); 86*11963SAfshin.Ardakani@Sun.COM return (strlen(str) + 1); 87*11963SAfshin.Ardakani@Sun.COM } 88*11963SAfshin.Ardakani@Sun.COM 89*11963SAfshin.Ardakani@Sun.COM int 90*11963SAfshin.Ardakani@Sun.COM smb_ascii_or_unicode_null_len(struct smb_request *sr) 91*11963SAfshin.Ardakani@Sun.COM { 92*11963SAfshin.Ardakani@Sun.COM if (sr->smb_flg2 & SMB_FLAGS2_UNICODE) 93*11963SAfshin.Ardakani@Sun.COM return (2); 94*11963SAfshin.Ardakani@Sun.COM return (1); 95*11963SAfshin.Ardakani@Sun.COM } 96*11963SAfshin.Ardakani@Sun.COM 97*11963SAfshin.Ardakani@Sun.COM /* 98*11963SAfshin.Ardakani@Sun.COM * Return B_TRUE if pattern contains wildcards 99*11963SAfshin.Ardakani@Sun.COM */ 100*11963SAfshin.Ardakani@Sun.COM boolean_t 101*11963SAfshin.Ardakani@Sun.COM smb_contains_wildcards(const char *pattern) 102*11963SAfshin.Ardakani@Sun.COM { 103*11963SAfshin.Ardakani@Sun.COM static const char *wildcards = "*?"; 104*11963SAfshin.Ardakani@Sun.COM 105*11963SAfshin.Ardakani@Sun.COM return (strpbrk(pattern, wildcards) != NULL); 106*11963SAfshin.Ardakani@Sun.COM } 107*11963SAfshin.Ardakani@Sun.COM 108*11963SAfshin.Ardakani@Sun.COM /* 109*11963SAfshin.Ardakani@Sun.COM * When converting wildcards a '.' in a name is treated as a base and 110*11963SAfshin.Ardakani@Sun.COM * extension separator even if the name is longer than 8.3. 111*11963SAfshin.Ardakani@Sun.COM * 112*11963SAfshin.Ardakani@Sun.COM * The '*' character matches an entire part of the name. For example, 113*11963SAfshin.Ardakani@Sun.COM * "*.abc" matches any name with an extension of "abc". 114*11963SAfshin.Ardakani@Sun.COM * 115*11963SAfshin.Ardakani@Sun.COM * The '?' character matches a single character. 116*11963SAfshin.Ardakani@Sun.COM * If the base contains all ? (8 or more) then it is treated as *. 117*11963SAfshin.Ardakani@Sun.COM * If the extension contains all ? (3 or more) then it is treated as *. 118*11963SAfshin.Ardakani@Sun.COM * 119*11963SAfshin.Ardakani@Sun.COM * Clients convert ASCII wildcards to Unicode wildcards as follows: 120*11963SAfshin.Ardakani@Sun.COM * 121*11963SAfshin.Ardakani@Sun.COM * ? is converted to > 122*11963SAfshin.Ardakani@Sun.COM * . is converted to " if it is followed by ? or * 123*11963SAfshin.Ardakani@Sun.COM * * is converted to < if it is followed by . 124*11963SAfshin.Ardakani@Sun.COM * 125*11963SAfshin.Ardakani@Sun.COM * Note that clients convert "*." to '< and drop the '.' but "*.txt" 126*11963SAfshin.Ardakani@Sun.COM * is sent as "<.TXT", i.e. 127*11963SAfshin.Ardakani@Sun.COM * 128*11963SAfshin.Ardakani@Sun.COM * dir *. -> dir < 129*11963SAfshin.Ardakani@Sun.COM * dir *.txt -> dir <.TXT 130*11963SAfshin.Ardakani@Sun.COM * 131*11963SAfshin.Ardakani@Sun.COM * Since " and < are illegal in Windows file names, we always convert 132*11963SAfshin.Ardakani@Sun.COM * these Unicode wildcards without checking the following character. 133*11963SAfshin.Ardakani@Sun.COM */ 134*11963SAfshin.Ardakani@Sun.COM void 135*11963SAfshin.Ardakani@Sun.COM smb_convert_wildcards(char *pattern) 136*11963SAfshin.Ardakani@Sun.COM { 137*11963SAfshin.Ardakani@Sun.COM static char *match_all[] = { 138*11963SAfshin.Ardakani@Sun.COM "*.", 139*11963SAfshin.Ardakani@Sun.COM "*.*" 140*11963SAfshin.Ardakani@Sun.COM }; 141*11963SAfshin.Ardakani@Sun.COM char *extension; 142*11963SAfshin.Ardakani@Sun.COM char *p; 143*11963SAfshin.Ardakani@Sun.COM int len; 144*11963SAfshin.Ardakani@Sun.COM int i; 145*11963SAfshin.Ardakani@Sun.COM 146*11963SAfshin.Ardakani@Sun.COM /* 147*11963SAfshin.Ardakani@Sun.COM * Special case "<" for "dir *.", and fast-track for "*". 148*11963SAfshin.Ardakani@Sun.COM */ 149*11963SAfshin.Ardakani@Sun.COM if ((*pattern == '<') || (*pattern == '*')) { 150*11963SAfshin.Ardakani@Sun.COM if (*(pattern + 1) == '\0') { 151*11963SAfshin.Ardakani@Sun.COM *pattern = '*'; 152*11963SAfshin.Ardakani@Sun.COM return; 153*11963SAfshin.Ardakani@Sun.COM } 154*11963SAfshin.Ardakani@Sun.COM } 155*11963SAfshin.Ardakani@Sun.COM 156*11963SAfshin.Ardakani@Sun.COM for (p = pattern; *p != '\0'; ++p) { 157*11963SAfshin.Ardakani@Sun.COM switch (*p) { 158*11963SAfshin.Ardakani@Sun.COM case '<': 159*11963SAfshin.Ardakani@Sun.COM *p = '*'; 160*11963SAfshin.Ardakani@Sun.COM break; 161*11963SAfshin.Ardakani@Sun.COM case '>': 162*11963SAfshin.Ardakani@Sun.COM *p = '?'; 163*11963SAfshin.Ardakani@Sun.COM break; 164*11963SAfshin.Ardakani@Sun.COM case '\"': 165*11963SAfshin.Ardakani@Sun.COM *p = '.'; 166*11963SAfshin.Ardakani@Sun.COM break; 167*11963SAfshin.Ardakani@Sun.COM default: 168*11963SAfshin.Ardakani@Sun.COM break; 169*11963SAfshin.Ardakani@Sun.COM } 170*11963SAfshin.Ardakani@Sun.COM } 171*11963SAfshin.Ardakani@Sun.COM 172*11963SAfshin.Ardakani@Sun.COM /* 173*11963SAfshin.Ardakani@Sun.COM * Replace "????????.ext" with "*.ext". 174*11963SAfshin.Ardakani@Sun.COM */ 175*11963SAfshin.Ardakani@Sun.COM p = pattern; 176*11963SAfshin.Ardakani@Sun.COM p += strspn(p, "?"); 177*11963SAfshin.Ardakani@Sun.COM if (*p == '.') { 178*11963SAfshin.Ardakani@Sun.COM *p = '\0'; 179*11963SAfshin.Ardakani@Sun.COM len = strlen(pattern); 180*11963SAfshin.Ardakani@Sun.COM *p = '.'; 181*11963SAfshin.Ardakani@Sun.COM if (len >= SMB_NAME83_BASELEN) { 182*11963SAfshin.Ardakani@Sun.COM *pattern = '*'; 183*11963SAfshin.Ardakani@Sun.COM (void) strlcpy(pattern + 1, p, MAXPATHLEN - 1); 184*11963SAfshin.Ardakani@Sun.COM } 185*11963SAfshin.Ardakani@Sun.COM } 186*11963SAfshin.Ardakani@Sun.COM 187*11963SAfshin.Ardakani@Sun.COM /* 188*11963SAfshin.Ardakani@Sun.COM * Replace "base.???" with 'base.*'. 189*11963SAfshin.Ardakani@Sun.COM */ 190*11963SAfshin.Ardakani@Sun.COM if ((extension = strrchr(pattern, '.')) != NULL) { 191*11963SAfshin.Ardakani@Sun.COM p = ++extension; 192*11963SAfshin.Ardakani@Sun.COM p += strspn(p, "?"); 193*11963SAfshin.Ardakani@Sun.COM if (*p == '\0') { 194*11963SAfshin.Ardakani@Sun.COM len = strlen(extension); 195*11963SAfshin.Ardakani@Sun.COM if (len >= SMB_NAME83_EXTLEN) { 196*11963SAfshin.Ardakani@Sun.COM *extension = '\0'; 197*11963SAfshin.Ardakani@Sun.COM (void) strlcat(pattern, "*", MAXPATHLEN); 198*11963SAfshin.Ardakani@Sun.COM } 199*11963SAfshin.Ardakani@Sun.COM } 200*11963SAfshin.Ardakani@Sun.COM } 201*11963SAfshin.Ardakani@Sun.COM 202*11963SAfshin.Ardakani@Sun.COM /* 203*11963SAfshin.Ardakani@Sun.COM * Replace anything that matches an entry in match_all with "*". 204*11963SAfshin.Ardakani@Sun.COM */ 205*11963SAfshin.Ardakani@Sun.COM for (i = 0; i < sizeof (match_all) / sizeof (match_all[0]); ++i) { 206*11963SAfshin.Ardakani@Sun.COM if (strcmp(pattern, match_all[i]) == 0) { 207*11963SAfshin.Ardakani@Sun.COM (void) strlcpy(pattern, "*", MAXPATHLEN); 208*11963SAfshin.Ardakani@Sun.COM break; 209*11963SAfshin.Ardakani@Sun.COM } 210*11963SAfshin.Ardakani@Sun.COM } 211*11963SAfshin.Ardakani@Sun.COM } 212*11963SAfshin.Ardakani@Sun.COM 213*11963SAfshin.Ardakani@Sun.COM /* 214*11963SAfshin.Ardakani@Sun.COM * smb_sattr_check 215*11963SAfshin.Ardakani@Sun.COM * 216*11963SAfshin.Ardakani@Sun.COM * Check file attributes against a search attribute (sattr) mask. 217*11963SAfshin.Ardakani@Sun.COM * 218*11963SAfshin.Ardakani@Sun.COM * Normal files, which includes READONLY and ARCHIVE, always pass 219*11963SAfshin.Ardakani@Sun.COM * this check. If the DIRECTORY, HIDDEN or SYSTEM special attributes 220*11963SAfshin.Ardakani@Sun.COM * are set then they must appear in the search mask. The special 221*11963SAfshin.Ardakani@Sun.COM * attributes are inclusive, i.e. all special attributes that appear 222*11963SAfshin.Ardakani@Sun.COM * in sattr must also appear in the file attributes for the check to 223*11963SAfshin.Ardakani@Sun.COM * pass. 224*11963SAfshin.Ardakani@Sun.COM * 225*11963SAfshin.Ardakani@Sun.COM * The following examples show how this works: 226*11963SAfshin.Ardakani@Sun.COM * 227*11963SAfshin.Ardakani@Sun.COM * fileA: READONLY 228*11963SAfshin.Ardakani@Sun.COM * fileB: 0 (no attributes = normal file) 229*11963SAfshin.Ardakani@Sun.COM * fileC: READONLY, ARCHIVE 230*11963SAfshin.Ardakani@Sun.COM * fileD: HIDDEN 231*11963SAfshin.Ardakani@Sun.COM * fileE: READONLY, HIDDEN, SYSTEM 232*11963SAfshin.Ardakani@Sun.COM * dirA: DIRECTORY 233*11963SAfshin.Ardakani@Sun.COM * 234*11963SAfshin.Ardakani@Sun.COM * search attribute: 0 235*11963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB and fileC. 236*11963SAfshin.Ardakani@Sun.COM * search attribute: HIDDEN 237*11963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB, fileC and fileD. 238*11963SAfshin.Ardakani@Sun.COM * search attribute: SYSTEM 239*11963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB and fileC. 240*11963SAfshin.Ardakani@Sun.COM * search attribute: DIRECTORY 241*11963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB, fileC and dirA. 242*11963SAfshin.Ardakani@Sun.COM * search attribute: HIDDEN and SYSTEM 243*11963SAfshin.Ardakani@Sun.COM * Returns: fileA, fileB, fileC, fileD and fileE. 244*11963SAfshin.Ardakani@Sun.COM * 245*11963SAfshin.Ardakani@Sun.COM * Returns true if the file and sattr match; otherwise, returns false. 246*11963SAfshin.Ardakani@Sun.COM */ 247*11963SAfshin.Ardakani@Sun.COM boolean_t 248*11963SAfshin.Ardakani@Sun.COM smb_sattr_check(uint16_t dosattr, uint16_t sattr) 249*11963SAfshin.Ardakani@Sun.COM { 250*11963SAfshin.Ardakani@Sun.COM if ((dosattr & FILE_ATTRIBUTE_DIRECTORY) && 251*11963SAfshin.Ardakani@Sun.COM !(sattr & FILE_ATTRIBUTE_DIRECTORY)) 252*11963SAfshin.Ardakani@Sun.COM return (B_FALSE); 253*11963SAfshin.Ardakani@Sun.COM 254*11963SAfshin.Ardakani@Sun.COM if ((dosattr & FILE_ATTRIBUTE_HIDDEN) && 255*11963SAfshin.Ardakani@Sun.COM !(sattr & FILE_ATTRIBUTE_HIDDEN)) 256*11963SAfshin.Ardakani@Sun.COM return (B_FALSE); 257*11963SAfshin.Ardakani@Sun.COM 258*11963SAfshin.Ardakani@Sun.COM if ((dosattr & FILE_ATTRIBUTE_SYSTEM) && 259*11963SAfshin.Ardakani@Sun.COM !(sattr & FILE_ATTRIBUTE_SYSTEM)) 260*11963SAfshin.Ardakani@Sun.COM return (B_FALSE); 261*11963SAfshin.Ardakani@Sun.COM 262*11963SAfshin.Ardakani@Sun.COM return (B_TRUE); 263*11963SAfshin.Ardakani@Sun.COM } 264*11963SAfshin.Ardakani@Sun.COM 265*11963SAfshin.Ardakani@Sun.COM int 266*11963SAfshin.Ardakani@Sun.COM microtime(timestruc_t *tvp) 267*11963SAfshin.Ardakani@Sun.COM { 268*11963SAfshin.Ardakani@Sun.COM tvp->tv_sec = gethrestime_sec(); 269*11963SAfshin.Ardakani@Sun.COM tvp->tv_nsec = 0; 270*11963SAfshin.Ardakani@Sun.COM return (0); 271*11963SAfshin.Ardakani@Sun.COM } 272*11963SAfshin.Ardakani@Sun.COM 273*11963SAfshin.Ardakani@Sun.COM int32_t 274*11963SAfshin.Ardakani@Sun.COM clock_get_milli_uptime() 275*11963SAfshin.Ardakani@Sun.COM { 276*11963SAfshin.Ardakani@Sun.COM return (TICK_TO_MSEC(ddi_get_lbolt())); 277*11963SAfshin.Ardakani@Sun.COM } 278*11963SAfshin.Ardakani@Sun.COM 279*11963SAfshin.Ardakani@Sun.COM int /*ARGSUSED*/ 280*11963SAfshin.Ardakani@Sun.COM smb_noop(void *p, size_t size, int foo) 281*11963SAfshin.Ardakani@Sun.COM { 282*11963SAfshin.Ardakani@Sun.COM return (0); 283*11963SAfshin.Ardakani@Sun.COM } 284*11963SAfshin.Ardakani@Sun.COM 285*11963SAfshin.Ardakani@Sun.COM /* 286*11963SAfshin.Ardakani@Sun.COM * smb_idpool_increment 287*11963SAfshin.Ardakani@Sun.COM * 288*11963SAfshin.Ardakani@Sun.COM * This function increments the ID pool by doubling the current size. This 289*11963SAfshin.Ardakani@Sun.COM * function assumes the caller entered the mutex of the pool. 290*11963SAfshin.Ardakani@Sun.COM */ 291*11963SAfshin.Ardakani@Sun.COM static int 292*11963SAfshin.Ardakani@Sun.COM smb_idpool_increment( 293*11963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool) 294*11963SAfshin.Ardakani@Sun.COM { 295*11963SAfshin.Ardakani@Sun.COM uint8_t *new_pool; 296*11963SAfshin.Ardakani@Sun.COM uint32_t new_size; 297*11963SAfshin.Ardakani@Sun.COM 298*11963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 299*11963SAfshin.Ardakani@Sun.COM 300*11963SAfshin.Ardakani@Sun.COM new_size = pool->id_size * 2; 301*11963SAfshin.Ardakani@Sun.COM if (new_size <= SMB_IDPOOL_MAX_SIZE) { 302*11963SAfshin.Ardakani@Sun.COM new_pool = kmem_alloc(new_size / 8, KM_NOSLEEP); 303*11963SAfshin.Ardakani@Sun.COM if (new_pool) { 304*11963SAfshin.Ardakani@Sun.COM bzero(new_pool, new_size / 8); 305*11963SAfshin.Ardakani@Sun.COM bcopy(pool->id_pool, new_pool, pool->id_size / 8); 306*11963SAfshin.Ardakani@Sun.COM kmem_free(pool->id_pool, pool->id_size / 8); 307*11963SAfshin.Ardakani@Sun.COM pool->id_pool = new_pool; 308*11963SAfshin.Ardakani@Sun.COM pool->id_free_counter += new_size - pool->id_size; 309*11963SAfshin.Ardakani@Sun.COM pool->id_max_free_counter += new_size - pool->id_size; 310*11963SAfshin.Ardakani@Sun.COM pool->id_size = new_size; 311*11963SAfshin.Ardakani@Sun.COM pool->id_idx_msk = (new_size / 8) - 1; 312*11963SAfshin.Ardakani@Sun.COM if (new_size >= SMB_IDPOOL_MAX_SIZE) { 313*11963SAfshin.Ardakani@Sun.COM /* id -1 made unavailable */ 314*11963SAfshin.Ardakani@Sun.COM pool->id_pool[pool->id_idx_msk] = 0x80; 315*11963SAfshin.Ardakani@Sun.COM pool->id_free_counter--; 316*11963SAfshin.Ardakani@Sun.COM pool->id_max_free_counter--; 317*11963SAfshin.Ardakani@Sun.COM } 318*11963SAfshin.Ardakani@Sun.COM return (0); 319*11963SAfshin.Ardakani@Sun.COM } 320*11963SAfshin.Ardakani@Sun.COM } 321*11963SAfshin.Ardakani@Sun.COM return (-1); 322*11963SAfshin.Ardakani@Sun.COM } 323*11963SAfshin.Ardakani@Sun.COM 324*11963SAfshin.Ardakani@Sun.COM /* 325*11963SAfshin.Ardakani@Sun.COM * smb_idpool_constructor 326*11963SAfshin.Ardakani@Sun.COM * 327*11963SAfshin.Ardakani@Sun.COM * This function initializes the pool structure provided. 328*11963SAfshin.Ardakani@Sun.COM */ 329*11963SAfshin.Ardakani@Sun.COM int 330*11963SAfshin.Ardakani@Sun.COM smb_idpool_constructor( 331*11963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool) 332*11963SAfshin.Ardakani@Sun.COM { 333*11963SAfshin.Ardakani@Sun.COM 334*11963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic != SMB_IDPOOL_MAGIC); 335*11963SAfshin.Ardakani@Sun.COM 336*11963SAfshin.Ardakani@Sun.COM pool->id_size = SMB_IDPOOL_MIN_SIZE; 337*11963SAfshin.Ardakani@Sun.COM pool->id_idx_msk = (SMB_IDPOOL_MIN_SIZE / 8) - 1; 338*11963SAfshin.Ardakani@Sun.COM pool->id_free_counter = SMB_IDPOOL_MIN_SIZE - 1; 339*11963SAfshin.Ardakani@Sun.COM pool->id_max_free_counter = SMB_IDPOOL_MIN_SIZE - 1; 340*11963SAfshin.Ardakani@Sun.COM pool->id_bit = 0x02; 341*11963SAfshin.Ardakani@Sun.COM pool->id_bit_idx = 1; 342*11963SAfshin.Ardakani@Sun.COM pool->id_idx = 0; 343*11963SAfshin.Ardakani@Sun.COM pool->id_pool = (uint8_t *)kmem_alloc((SMB_IDPOOL_MIN_SIZE / 8), 344*11963SAfshin.Ardakani@Sun.COM KM_SLEEP); 345*11963SAfshin.Ardakani@Sun.COM bzero(pool->id_pool, (SMB_IDPOOL_MIN_SIZE / 8)); 346*11963SAfshin.Ardakani@Sun.COM /* -1 id made unavailable */ 347*11963SAfshin.Ardakani@Sun.COM pool->id_pool[0] = 0x01; /* id 0 made unavailable */ 348*11963SAfshin.Ardakani@Sun.COM mutex_init(&pool->id_mutex, NULL, MUTEX_DEFAULT, NULL); 349*11963SAfshin.Ardakani@Sun.COM pool->id_magic = SMB_IDPOOL_MAGIC; 350*11963SAfshin.Ardakani@Sun.COM return (0); 351*11963SAfshin.Ardakani@Sun.COM } 352*11963SAfshin.Ardakani@Sun.COM 353*11963SAfshin.Ardakani@Sun.COM /* 354*11963SAfshin.Ardakani@Sun.COM * smb_idpool_destructor 355*11963SAfshin.Ardakani@Sun.COM * 356*11963SAfshin.Ardakani@Sun.COM * This function tears down and frees the resources associated with the 357*11963SAfshin.Ardakani@Sun.COM * pool provided. 358*11963SAfshin.Ardakani@Sun.COM */ 359*11963SAfshin.Ardakani@Sun.COM void 360*11963SAfshin.Ardakani@Sun.COM smb_idpool_destructor( 361*11963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool) 362*11963SAfshin.Ardakani@Sun.COM { 363*11963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 364*11963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_free_counter == pool->id_max_free_counter); 365*11963SAfshin.Ardakani@Sun.COM pool->id_magic = (uint32_t)~SMB_IDPOOL_MAGIC; 366*11963SAfshin.Ardakani@Sun.COM mutex_destroy(&pool->id_mutex); 367*11963SAfshin.Ardakani@Sun.COM kmem_free(pool->id_pool, (size_t)(pool->id_size / 8)); 368*11963SAfshin.Ardakani@Sun.COM } 369*11963SAfshin.Ardakani@Sun.COM 370*11963SAfshin.Ardakani@Sun.COM /* 371*11963SAfshin.Ardakani@Sun.COM * smb_idpool_alloc 372*11963SAfshin.Ardakani@Sun.COM * 373*11963SAfshin.Ardakani@Sun.COM * This function allocates an ID from the pool provided. 374*11963SAfshin.Ardakani@Sun.COM */ 375*11963SAfshin.Ardakani@Sun.COM int 376*11963SAfshin.Ardakani@Sun.COM smb_idpool_alloc( 377*11963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool, 378*11963SAfshin.Ardakani@Sun.COM uint16_t *id) 379*11963SAfshin.Ardakani@Sun.COM { 380*11963SAfshin.Ardakani@Sun.COM uint32_t i; 381*11963SAfshin.Ardakani@Sun.COM uint8_t bit; 382*11963SAfshin.Ardakani@Sun.COM uint8_t bit_idx; 383*11963SAfshin.Ardakani@Sun.COM uint8_t byte; 384*11963SAfshin.Ardakani@Sun.COM 385*11963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 386*11963SAfshin.Ardakani@Sun.COM 387*11963SAfshin.Ardakani@Sun.COM mutex_enter(&pool->id_mutex); 388*11963SAfshin.Ardakani@Sun.COM if ((pool->id_free_counter == 0) && smb_idpool_increment(pool)) { 389*11963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 390*11963SAfshin.Ardakani@Sun.COM return (-1); 391*11963SAfshin.Ardakani@Sun.COM } 392*11963SAfshin.Ardakani@Sun.COM 393*11963SAfshin.Ardakani@Sun.COM i = pool->id_size; 394*11963SAfshin.Ardakani@Sun.COM while (i) { 395*11963SAfshin.Ardakani@Sun.COM bit = pool->id_bit; 396*11963SAfshin.Ardakani@Sun.COM bit_idx = pool->id_bit_idx; 397*11963SAfshin.Ardakani@Sun.COM byte = pool->id_pool[pool->id_idx]; 398*11963SAfshin.Ardakani@Sun.COM while (bit) { 399*11963SAfshin.Ardakani@Sun.COM if (byte & bit) { 400*11963SAfshin.Ardakani@Sun.COM bit = bit << 1; 401*11963SAfshin.Ardakani@Sun.COM bit_idx++; 402*11963SAfshin.Ardakani@Sun.COM continue; 403*11963SAfshin.Ardakani@Sun.COM } 404*11963SAfshin.Ardakani@Sun.COM pool->id_pool[pool->id_idx] |= bit; 405*11963SAfshin.Ardakani@Sun.COM *id = (uint16_t)(pool->id_idx * 8 + (uint32_t)bit_idx); 406*11963SAfshin.Ardakani@Sun.COM pool->id_free_counter--; 407*11963SAfshin.Ardakani@Sun.COM pool->id_bit = bit; 408*11963SAfshin.Ardakani@Sun.COM pool->id_bit_idx = bit_idx; 409*11963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 410*11963SAfshin.Ardakani@Sun.COM return (0); 411*11963SAfshin.Ardakani@Sun.COM } 412*11963SAfshin.Ardakani@Sun.COM pool->id_bit = 1; 413*11963SAfshin.Ardakani@Sun.COM pool->id_bit_idx = 0; 414*11963SAfshin.Ardakani@Sun.COM pool->id_idx++; 415*11963SAfshin.Ardakani@Sun.COM pool->id_idx &= pool->id_idx_msk; 416*11963SAfshin.Ardakani@Sun.COM --i; 417*11963SAfshin.Ardakani@Sun.COM } 418*11963SAfshin.Ardakani@Sun.COM /* 419*11963SAfshin.Ardakani@Sun.COM * This section of code shouldn't be reached. If there are IDs 420*11963SAfshin.Ardakani@Sun.COM * available and none could be found there's a problem. 421*11963SAfshin.Ardakani@Sun.COM */ 422*11963SAfshin.Ardakani@Sun.COM ASSERT(0); 423*11963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 424*11963SAfshin.Ardakani@Sun.COM return (-1); 425*11963SAfshin.Ardakani@Sun.COM } 426*11963SAfshin.Ardakani@Sun.COM 427*11963SAfshin.Ardakani@Sun.COM /* 428*11963SAfshin.Ardakani@Sun.COM * smb_idpool_free 429*11963SAfshin.Ardakani@Sun.COM * 430*11963SAfshin.Ardakani@Sun.COM * This function frees the ID provided. 431*11963SAfshin.Ardakani@Sun.COM */ 432*11963SAfshin.Ardakani@Sun.COM void 433*11963SAfshin.Ardakani@Sun.COM smb_idpool_free( 434*11963SAfshin.Ardakani@Sun.COM smb_idpool_t *pool, 435*11963SAfshin.Ardakani@Sun.COM uint16_t id) 436*11963SAfshin.Ardakani@Sun.COM { 437*11963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_magic == SMB_IDPOOL_MAGIC); 438*11963SAfshin.Ardakani@Sun.COM ASSERT(id != 0); 439*11963SAfshin.Ardakani@Sun.COM ASSERT(id != 0xFFFF); 440*11963SAfshin.Ardakani@Sun.COM 441*11963SAfshin.Ardakani@Sun.COM mutex_enter(&pool->id_mutex); 442*11963SAfshin.Ardakani@Sun.COM if (pool->id_pool[id >> 3] & (1 << (id & 7))) { 443*11963SAfshin.Ardakani@Sun.COM pool->id_pool[id >> 3] &= ~(1 << (id & 7)); 444*11963SAfshin.Ardakani@Sun.COM pool->id_free_counter++; 445*11963SAfshin.Ardakani@Sun.COM ASSERT(pool->id_free_counter <= pool->id_max_free_counter); 446*11963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 447*11963SAfshin.Ardakani@Sun.COM return; 448*11963SAfshin.Ardakani@Sun.COM } 449*11963SAfshin.Ardakani@Sun.COM /* Freeing a free ID. */ 450*11963SAfshin.Ardakani@Sun.COM ASSERT(0); 451*11963SAfshin.Ardakani@Sun.COM mutex_exit(&pool->id_mutex); 452*11963SAfshin.Ardakani@Sun.COM } 453*11963SAfshin.Ardakani@Sun.COM 454*11963SAfshin.Ardakani@Sun.COM /* 455*11963SAfshin.Ardakani@Sun.COM * Initialize the llist delete queue object cache. 456*11963SAfshin.Ardakani@Sun.COM */ 457*11963SAfshin.Ardakani@Sun.COM void 458*11963SAfshin.Ardakani@Sun.COM smb_llist_init(void) 459*11963SAfshin.Ardakani@Sun.COM { 460*11963SAfshin.Ardakani@Sun.COM if (smb_llist_initialized) 461*11963SAfshin.Ardakani@Sun.COM return; 462*11963SAfshin.Ardakani@Sun.COM 463*11963SAfshin.Ardakani@Sun.COM smb_dtor_cache = kmem_cache_create("smb_dtor_cache", 464*11963SAfshin.Ardakani@Sun.COM sizeof (smb_dtor_t), 8, NULL, NULL, NULL, NULL, NULL, 0); 465*11963SAfshin.Ardakani@Sun.COM 466*11963SAfshin.Ardakani@Sun.COM smb_llist_initialized = B_TRUE; 467*11963SAfshin.Ardakani@Sun.COM } 468*11963SAfshin.Ardakani@Sun.COM 469*11963SAfshin.Ardakani@Sun.COM /* 470*11963SAfshin.Ardakani@Sun.COM * Destroy the llist delete queue object cache. 471*11963SAfshin.Ardakani@Sun.COM */ 472*11963SAfshin.Ardakani@Sun.COM void 473*11963SAfshin.Ardakani@Sun.COM smb_llist_fini(void) 474*11963SAfshin.Ardakani@Sun.COM { 475*11963SAfshin.Ardakani@Sun.COM if (!smb_llist_initialized) 476*11963SAfshin.Ardakani@Sun.COM return; 477*11963SAfshin.Ardakani@Sun.COM 478*11963SAfshin.Ardakani@Sun.COM kmem_cache_destroy(smb_dtor_cache); 479*11963SAfshin.Ardakani@Sun.COM smb_llist_initialized = B_FALSE; 480*11963SAfshin.Ardakani@Sun.COM } 481*11963SAfshin.Ardakani@Sun.COM 482*11963SAfshin.Ardakani@Sun.COM /* 483*11963SAfshin.Ardakani@Sun.COM * smb_llist_constructor 484*11963SAfshin.Ardakani@Sun.COM * 485*11963SAfshin.Ardakani@Sun.COM * This function initializes a locked list. 486*11963SAfshin.Ardakani@Sun.COM */ 487*11963SAfshin.Ardakani@Sun.COM void 488*11963SAfshin.Ardakani@Sun.COM smb_llist_constructor( 489*11963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 490*11963SAfshin.Ardakani@Sun.COM size_t size, 491*11963SAfshin.Ardakani@Sun.COM size_t offset) 492*11963SAfshin.Ardakani@Sun.COM { 493*11963SAfshin.Ardakani@Sun.COM rw_init(&ll->ll_lock, NULL, RW_DEFAULT, NULL); 494*11963SAfshin.Ardakani@Sun.COM mutex_init(&ll->ll_mutex, NULL, MUTEX_DEFAULT, NULL); 495*11963SAfshin.Ardakani@Sun.COM list_create(&ll->ll_list, size, offset); 496*11963SAfshin.Ardakani@Sun.COM list_create(&ll->ll_deleteq, sizeof (smb_dtor_t), 497*11963SAfshin.Ardakani@Sun.COM offsetof(smb_dtor_t, dt_lnd)); 498*11963SAfshin.Ardakani@Sun.COM ll->ll_count = 0; 499*11963SAfshin.Ardakani@Sun.COM ll->ll_wrop = 0; 500*11963SAfshin.Ardakani@Sun.COM ll->ll_deleteq_count = 0; 501*11963SAfshin.Ardakani@Sun.COM } 502*11963SAfshin.Ardakani@Sun.COM 503*11963SAfshin.Ardakani@Sun.COM /* 504*11963SAfshin.Ardakani@Sun.COM * Flush the delete queue and destroy a locked list. 505*11963SAfshin.Ardakani@Sun.COM */ 506*11963SAfshin.Ardakani@Sun.COM void 507*11963SAfshin.Ardakani@Sun.COM smb_llist_destructor( 508*11963SAfshin.Ardakani@Sun.COM smb_llist_t *ll) 509*11963SAfshin.Ardakani@Sun.COM { 510*11963SAfshin.Ardakani@Sun.COM smb_llist_flush(ll); 511*11963SAfshin.Ardakani@Sun.COM 512*11963SAfshin.Ardakani@Sun.COM ASSERT(ll->ll_count == 0); 513*11963SAfshin.Ardakani@Sun.COM ASSERT(ll->ll_deleteq_count == 0); 514*11963SAfshin.Ardakani@Sun.COM 515*11963SAfshin.Ardakani@Sun.COM rw_destroy(&ll->ll_lock); 516*11963SAfshin.Ardakani@Sun.COM list_destroy(&ll->ll_list); 517*11963SAfshin.Ardakani@Sun.COM list_destroy(&ll->ll_deleteq); 518*11963SAfshin.Ardakani@Sun.COM mutex_destroy(&ll->ll_mutex); 519*11963SAfshin.Ardakani@Sun.COM } 520*11963SAfshin.Ardakani@Sun.COM 521*11963SAfshin.Ardakani@Sun.COM /* 522*11963SAfshin.Ardakani@Sun.COM * Post an object to the delete queue. The delete queue will be processed 523*11963SAfshin.Ardakani@Sun.COM * during list exit or list destruction. Objects are often posted for 524*11963SAfshin.Ardakani@Sun.COM * deletion during list iteration (while the list is locked) but that is 525*11963SAfshin.Ardakani@Sun.COM * not required, and an object can be posted at any time. 526*11963SAfshin.Ardakani@Sun.COM */ 527*11963SAfshin.Ardakani@Sun.COM void 528*11963SAfshin.Ardakani@Sun.COM smb_llist_post(smb_llist_t *ll, void *object, smb_dtorproc_t dtorproc) 529*11963SAfshin.Ardakani@Sun.COM { 530*11963SAfshin.Ardakani@Sun.COM smb_dtor_t *dtor; 531*11963SAfshin.Ardakani@Sun.COM 532*11963SAfshin.Ardakani@Sun.COM ASSERT((object != NULL) && (dtorproc != NULL)); 533*11963SAfshin.Ardakani@Sun.COM 534*11963SAfshin.Ardakani@Sun.COM dtor = kmem_cache_alloc(smb_dtor_cache, KM_SLEEP); 535*11963SAfshin.Ardakani@Sun.COM bzero(dtor, sizeof (smb_dtor_t)); 536*11963SAfshin.Ardakani@Sun.COM dtor->dt_magic = SMB_DTOR_MAGIC; 537*11963SAfshin.Ardakani@Sun.COM dtor->dt_object = object; 538*11963SAfshin.Ardakani@Sun.COM dtor->dt_proc = dtorproc; 539*11963SAfshin.Ardakani@Sun.COM 540*11963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex); 541*11963SAfshin.Ardakani@Sun.COM list_insert_tail(&ll->ll_deleteq, dtor); 542*11963SAfshin.Ardakani@Sun.COM ++ll->ll_deleteq_count; 543*11963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex); 544*11963SAfshin.Ardakani@Sun.COM } 545*11963SAfshin.Ardakani@Sun.COM 546*11963SAfshin.Ardakani@Sun.COM /* 547*11963SAfshin.Ardakani@Sun.COM * Exit the list lock and process the delete queue. 548*11963SAfshin.Ardakani@Sun.COM */ 549*11963SAfshin.Ardakani@Sun.COM void 550*11963SAfshin.Ardakani@Sun.COM smb_llist_exit(smb_llist_t *ll) 551*11963SAfshin.Ardakani@Sun.COM { 552*11963SAfshin.Ardakani@Sun.COM rw_exit(&ll->ll_lock); 553*11963SAfshin.Ardakani@Sun.COM smb_llist_flush(ll); 554*11963SAfshin.Ardakani@Sun.COM } 555*11963SAfshin.Ardakani@Sun.COM 556*11963SAfshin.Ardakani@Sun.COM /* 557*11963SAfshin.Ardakani@Sun.COM * Flush the list delete queue. The mutex is dropped across the destructor 558*11963SAfshin.Ardakani@Sun.COM * call in case this leads to additional objects being posted to the delete 559*11963SAfshin.Ardakani@Sun.COM * queue. 560*11963SAfshin.Ardakani@Sun.COM */ 561*11963SAfshin.Ardakani@Sun.COM static void 562*11963SAfshin.Ardakani@Sun.COM smb_llist_flush(smb_llist_t *ll) 563*11963SAfshin.Ardakani@Sun.COM { 564*11963SAfshin.Ardakani@Sun.COM smb_dtor_t *dtor; 565*11963SAfshin.Ardakani@Sun.COM 566*11963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex); 567*11963SAfshin.Ardakani@Sun.COM 568*11963SAfshin.Ardakani@Sun.COM dtor = list_head(&ll->ll_deleteq); 569*11963SAfshin.Ardakani@Sun.COM while (dtor != NULL) { 570*11963SAfshin.Ardakani@Sun.COM SMB_DTOR_VALID(dtor); 571*11963SAfshin.Ardakani@Sun.COM ASSERT((dtor->dt_object != NULL) && (dtor->dt_proc != NULL)); 572*11963SAfshin.Ardakani@Sun.COM list_remove(&ll->ll_deleteq, dtor); 573*11963SAfshin.Ardakani@Sun.COM --ll->ll_deleteq_count; 574*11963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex); 575*11963SAfshin.Ardakani@Sun.COM 576*11963SAfshin.Ardakani@Sun.COM dtor->dt_proc(dtor->dt_object); 577*11963SAfshin.Ardakani@Sun.COM 578*11963SAfshin.Ardakani@Sun.COM dtor->dt_magic = (uint32_t)~SMB_DTOR_MAGIC; 579*11963SAfshin.Ardakani@Sun.COM kmem_cache_free(smb_dtor_cache, dtor); 580*11963SAfshin.Ardakani@Sun.COM mutex_enter(&ll->ll_mutex); 581*11963SAfshin.Ardakani@Sun.COM dtor = list_head(&ll->ll_deleteq); 582*11963SAfshin.Ardakani@Sun.COM } 583*11963SAfshin.Ardakani@Sun.COM 584*11963SAfshin.Ardakani@Sun.COM mutex_exit(&ll->ll_mutex); 585*11963SAfshin.Ardakani@Sun.COM } 586*11963SAfshin.Ardakani@Sun.COM 587*11963SAfshin.Ardakani@Sun.COM /* 588*11963SAfshin.Ardakani@Sun.COM * smb_llist_upgrade 589*11963SAfshin.Ardakani@Sun.COM * 590*11963SAfshin.Ardakani@Sun.COM * This function tries to upgrade the lock of the locked list. It assumes the 591*11963SAfshin.Ardakani@Sun.COM * locked has already been entered in RW_READER mode. It first tries using the 592*11963SAfshin.Ardakani@Sun.COM * Solaris function rw_tryupgrade(). If that call fails the lock is released 593*11963SAfshin.Ardakani@Sun.COM * and reentered in RW_WRITER mode. In that last case a window is opened during 594*11963SAfshin.Ardakani@Sun.COM * which the contents of the list may have changed. The return code indicates 595*11963SAfshin.Ardakani@Sun.COM * whether or not the list was modified when the lock was exited. 596*11963SAfshin.Ardakani@Sun.COM */ 597*11963SAfshin.Ardakani@Sun.COM int smb_llist_upgrade( 598*11963SAfshin.Ardakani@Sun.COM smb_llist_t *ll) 599*11963SAfshin.Ardakani@Sun.COM { 600*11963SAfshin.Ardakani@Sun.COM uint64_t wrop; 601*11963SAfshin.Ardakani@Sun.COM 602*11963SAfshin.Ardakani@Sun.COM if (rw_tryupgrade(&ll->ll_lock) != 0) { 603*11963SAfshin.Ardakani@Sun.COM return (0); 604*11963SAfshin.Ardakani@Sun.COM } 605*11963SAfshin.Ardakani@Sun.COM wrop = ll->ll_wrop; 606*11963SAfshin.Ardakani@Sun.COM rw_exit(&ll->ll_lock); 607*11963SAfshin.Ardakani@Sun.COM rw_enter(&ll->ll_lock, RW_WRITER); 608*11963SAfshin.Ardakani@Sun.COM return (wrop != ll->ll_wrop); 609*11963SAfshin.Ardakani@Sun.COM } 610*11963SAfshin.Ardakani@Sun.COM 611*11963SAfshin.Ardakani@Sun.COM /* 612*11963SAfshin.Ardakani@Sun.COM * smb_llist_insert_head 613*11963SAfshin.Ardakani@Sun.COM * 614*11963SAfshin.Ardakani@Sun.COM * This function inserts the object passed a the beginning of the list. This 615*11963SAfshin.Ardakani@Sun.COM * function assumes the lock of the list has already been entered. 616*11963SAfshin.Ardakani@Sun.COM */ 617*11963SAfshin.Ardakani@Sun.COM void 618*11963SAfshin.Ardakani@Sun.COM smb_llist_insert_head( 619*11963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 620*11963SAfshin.Ardakani@Sun.COM void *obj) 621*11963SAfshin.Ardakani@Sun.COM { 622*11963SAfshin.Ardakani@Sun.COM list_insert_head(&ll->ll_list, obj); 623*11963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop; 624*11963SAfshin.Ardakani@Sun.COM ++ll->ll_count; 625*11963SAfshin.Ardakani@Sun.COM } 626*11963SAfshin.Ardakani@Sun.COM 627*11963SAfshin.Ardakani@Sun.COM /* 628*11963SAfshin.Ardakani@Sun.COM * smb_llist_insert_tail 629*11963SAfshin.Ardakani@Sun.COM * 630*11963SAfshin.Ardakani@Sun.COM * This function appends to the object passed to the list. This function assumes 631*11963SAfshin.Ardakani@Sun.COM * the lock of the list has already been entered. 632*11963SAfshin.Ardakani@Sun.COM * 633*11963SAfshin.Ardakani@Sun.COM */ 634*11963SAfshin.Ardakani@Sun.COM void 635*11963SAfshin.Ardakani@Sun.COM smb_llist_insert_tail( 636*11963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 637*11963SAfshin.Ardakani@Sun.COM void *obj) 638*11963SAfshin.Ardakani@Sun.COM { 639*11963SAfshin.Ardakani@Sun.COM list_insert_tail(&ll->ll_list, obj); 640*11963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop; 641*11963SAfshin.Ardakani@Sun.COM ++ll->ll_count; 642*11963SAfshin.Ardakani@Sun.COM } 643*11963SAfshin.Ardakani@Sun.COM 644*11963SAfshin.Ardakani@Sun.COM /* 645*11963SAfshin.Ardakani@Sun.COM * smb_llist_remove 646*11963SAfshin.Ardakani@Sun.COM * 647*11963SAfshin.Ardakani@Sun.COM * This function removes the object passed from the list. This function assumes 648*11963SAfshin.Ardakani@Sun.COM * the lock of the list has already been entered. 649*11963SAfshin.Ardakani@Sun.COM */ 650*11963SAfshin.Ardakani@Sun.COM void 651*11963SAfshin.Ardakani@Sun.COM smb_llist_remove( 652*11963SAfshin.Ardakani@Sun.COM smb_llist_t *ll, 653*11963SAfshin.Ardakani@Sun.COM void *obj) 654*11963SAfshin.Ardakani@Sun.COM { 655*11963SAfshin.Ardakani@Sun.COM list_remove(&ll->ll_list, obj); 656*11963SAfshin.Ardakani@Sun.COM ++ll->ll_wrop; 657*11963SAfshin.Ardakani@Sun.COM --ll->ll_count; 658*11963SAfshin.Ardakani@Sun.COM } 659*11963SAfshin.Ardakani@Sun.COM 660*11963SAfshin.Ardakani@Sun.COM /* 661*11963SAfshin.Ardakani@Sun.COM * smb_llist_get_count 662*11963SAfshin.Ardakani@Sun.COM * 663*11963SAfshin.Ardakani@Sun.COM * This function returns the number of elements in the specified list. 664*11963SAfshin.Ardakani@Sun.COM */ 665*11963SAfshin.Ardakani@Sun.COM uint32_t 666*11963SAfshin.Ardakani@Sun.COM smb_llist_get_count( 667*11963SAfshin.Ardakani@Sun.COM smb_llist_t *ll) 668*11963SAfshin.Ardakani@Sun.COM { 669*11963SAfshin.Ardakani@Sun.COM return (ll->ll_count); 670*11963SAfshin.Ardakani@Sun.COM } 671*11963SAfshin.Ardakani@Sun.COM 672*11963SAfshin.Ardakani@Sun.COM /* 673*11963SAfshin.Ardakani@Sun.COM * smb_slist_constructor 674*11963SAfshin.Ardakani@Sun.COM * 675*11963SAfshin.Ardakani@Sun.COM * Synchronized list constructor. 676*11963SAfshin.Ardakani@Sun.COM */ 677*11963SAfshin.Ardakani@Sun.COM void 678*11963SAfshin.Ardakani@Sun.COM smb_slist_constructor( 679*11963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 680*11963SAfshin.Ardakani@Sun.COM size_t size, 681*11963SAfshin.Ardakani@Sun.COM size_t offset) 682*11963SAfshin.Ardakani@Sun.COM { 683*11963SAfshin.Ardakani@Sun.COM mutex_init(&sl->sl_mutex, NULL, MUTEX_DEFAULT, NULL); 684*11963SAfshin.Ardakani@Sun.COM cv_init(&sl->sl_cv, NULL, CV_DEFAULT, NULL); 685*11963SAfshin.Ardakani@Sun.COM list_create(&sl->sl_list, size, offset); 686*11963SAfshin.Ardakani@Sun.COM sl->sl_count = 0; 687*11963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 688*11963SAfshin.Ardakani@Sun.COM } 689*11963SAfshin.Ardakani@Sun.COM 690*11963SAfshin.Ardakani@Sun.COM /* 691*11963SAfshin.Ardakani@Sun.COM * smb_slist_destructor 692*11963SAfshin.Ardakani@Sun.COM * 693*11963SAfshin.Ardakani@Sun.COM * Synchronized list destructor. 694*11963SAfshin.Ardakani@Sun.COM */ 695*11963SAfshin.Ardakani@Sun.COM void 696*11963SAfshin.Ardakani@Sun.COM smb_slist_destructor( 697*11963SAfshin.Ardakani@Sun.COM smb_slist_t *sl) 698*11963SAfshin.Ardakani@Sun.COM { 699*11963SAfshin.Ardakani@Sun.COM ASSERT(sl->sl_count == 0); 700*11963SAfshin.Ardakani@Sun.COM 701*11963SAfshin.Ardakani@Sun.COM mutex_destroy(&sl->sl_mutex); 702*11963SAfshin.Ardakani@Sun.COM cv_destroy(&sl->sl_cv); 703*11963SAfshin.Ardakani@Sun.COM list_destroy(&sl->sl_list); 704*11963SAfshin.Ardakani@Sun.COM } 705*11963SAfshin.Ardakani@Sun.COM 706*11963SAfshin.Ardakani@Sun.COM /* 707*11963SAfshin.Ardakani@Sun.COM * smb_slist_insert_head 708*11963SAfshin.Ardakani@Sun.COM * 709*11963SAfshin.Ardakani@Sun.COM * This function inserts the object passed a the beginning of the list. 710*11963SAfshin.Ardakani@Sun.COM */ 711*11963SAfshin.Ardakani@Sun.COM void 712*11963SAfshin.Ardakani@Sun.COM smb_slist_insert_head( 713*11963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 714*11963SAfshin.Ardakani@Sun.COM void *obj) 715*11963SAfshin.Ardakani@Sun.COM { 716*11963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 717*11963SAfshin.Ardakani@Sun.COM list_insert_head(&sl->sl_list, obj); 718*11963SAfshin.Ardakani@Sun.COM ++sl->sl_count; 719*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 720*11963SAfshin.Ardakani@Sun.COM } 721*11963SAfshin.Ardakani@Sun.COM 722*11963SAfshin.Ardakani@Sun.COM /* 723*11963SAfshin.Ardakani@Sun.COM * smb_slist_insert_tail 724*11963SAfshin.Ardakani@Sun.COM * 725*11963SAfshin.Ardakani@Sun.COM * This function appends the object passed to the list. 726*11963SAfshin.Ardakani@Sun.COM */ 727*11963SAfshin.Ardakani@Sun.COM void 728*11963SAfshin.Ardakani@Sun.COM smb_slist_insert_tail( 729*11963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 730*11963SAfshin.Ardakani@Sun.COM void *obj) 731*11963SAfshin.Ardakani@Sun.COM { 732*11963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 733*11963SAfshin.Ardakani@Sun.COM list_insert_tail(&sl->sl_list, obj); 734*11963SAfshin.Ardakani@Sun.COM ++sl->sl_count; 735*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 736*11963SAfshin.Ardakani@Sun.COM } 737*11963SAfshin.Ardakani@Sun.COM 738*11963SAfshin.Ardakani@Sun.COM /* 739*11963SAfshin.Ardakani@Sun.COM * smb_llist_remove 740*11963SAfshin.Ardakani@Sun.COM * 741*11963SAfshin.Ardakani@Sun.COM * This function removes the object passed by the caller from the list. 742*11963SAfshin.Ardakani@Sun.COM */ 743*11963SAfshin.Ardakani@Sun.COM void 744*11963SAfshin.Ardakani@Sun.COM smb_slist_remove( 745*11963SAfshin.Ardakani@Sun.COM smb_slist_t *sl, 746*11963SAfshin.Ardakani@Sun.COM void *obj) 747*11963SAfshin.Ardakani@Sun.COM { 748*11963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 749*11963SAfshin.Ardakani@Sun.COM list_remove(&sl->sl_list, obj); 750*11963SAfshin.Ardakani@Sun.COM if ((--sl->sl_count == 0) && (sl->sl_waiting)) { 751*11963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 752*11963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv); 753*11963SAfshin.Ardakani@Sun.COM } 754*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 755*11963SAfshin.Ardakani@Sun.COM } 756*11963SAfshin.Ardakani@Sun.COM 757*11963SAfshin.Ardakani@Sun.COM /* 758*11963SAfshin.Ardakani@Sun.COM * smb_slist_move_tail 759*11963SAfshin.Ardakani@Sun.COM * 760*11963SAfshin.Ardakani@Sun.COM * This function transfers all the contents of the synchronized list to the 761*11963SAfshin.Ardakani@Sun.COM * list_t provided. It returns the number of objects transferred. 762*11963SAfshin.Ardakani@Sun.COM */ 763*11963SAfshin.Ardakani@Sun.COM uint32_t 764*11963SAfshin.Ardakani@Sun.COM smb_slist_move_tail( 765*11963SAfshin.Ardakani@Sun.COM list_t *lst, 766*11963SAfshin.Ardakani@Sun.COM smb_slist_t *sl) 767*11963SAfshin.Ardakani@Sun.COM { 768*11963SAfshin.Ardakani@Sun.COM uint32_t rv; 769*11963SAfshin.Ardakani@Sun.COM 770*11963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 771*11963SAfshin.Ardakani@Sun.COM rv = sl->sl_count; 772*11963SAfshin.Ardakani@Sun.COM if (sl->sl_count) { 773*11963SAfshin.Ardakani@Sun.COM list_move_tail(lst, &sl->sl_list); 774*11963SAfshin.Ardakani@Sun.COM sl->sl_count = 0; 775*11963SAfshin.Ardakani@Sun.COM if (sl->sl_waiting) { 776*11963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 777*11963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv); 778*11963SAfshin.Ardakani@Sun.COM } 779*11963SAfshin.Ardakani@Sun.COM } 780*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 781*11963SAfshin.Ardakani@Sun.COM return (rv); 782*11963SAfshin.Ardakani@Sun.COM } 783*11963SAfshin.Ardakani@Sun.COM 784*11963SAfshin.Ardakani@Sun.COM /* 785*11963SAfshin.Ardakani@Sun.COM * smb_slist_obj_move 786*11963SAfshin.Ardakani@Sun.COM * 787*11963SAfshin.Ardakani@Sun.COM * This function moves an object from one list to the end of the other list. It 788*11963SAfshin.Ardakani@Sun.COM * assumes the mutex of each list has been entered. 789*11963SAfshin.Ardakani@Sun.COM */ 790*11963SAfshin.Ardakani@Sun.COM void 791*11963SAfshin.Ardakani@Sun.COM smb_slist_obj_move( 792*11963SAfshin.Ardakani@Sun.COM smb_slist_t *dst, 793*11963SAfshin.Ardakani@Sun.COM smb_slist_t *src, 794*11963SAfshin.Ardakani@Sun.COM void *obj) 795*11963SAfshin.Ardakani@Sun.COM { 796*11963SAfshin.Ardakani@Sun.COM ASSERT(dst->sl_list.list_offset == src->sl_list.list_offset); 797*11963SAfshin.Ardakani@Sun.COM ASSERT(dst->sl_list.list_size == src->sl_list.list_size); 798*11963SAfshin.Ardakani@Sun.COM 799*11963SAfshin.Ardakani@Sun.COM list_remove(&src->sl_list, obj); 800*11963SAfshin.Ardakani@Sun.COM list_insert_tail(&dst->sl_list, obj); 801*11963SAfshin.Ardakani@Sun.COM dst->sl_count++; 802*11963SAfshin.Ardakani@Sun.COM src->sl_count--; 803*11963SAfshin.Ardakani@Sun.COM if ((src->sl_count == 0) && (src->sl_waiting)) { 804*11963SAfshin.Ardakani@Sun.COM src->sl_waiting = B_FALSE; 805*11963SAfshin.Ardakani@Sun.COM cv_broadcast(&src->sl_cv); 806*11963SAfshin.Ardakani@Sun.COM } 807*11963SAfshin.Ardakani@Sun.COM } 808*11963SAfshin.Ardakani@Sun.COM 809*11963SAfshin.Ardakani@Sun.COM /* 810*11963SAfshin.Ardakani@Sun.COM * smb_slist_wait_for_empty 811*11963SAfshin.Ardakani@Sun.COM * 812*11963SAfshin.Ardakani@Sun.COM * This function waits for a list to be emptied. 813*11963SAfshin.Ardakani@Sun.COM */ 814*11963SAfshin.Ardakani@Sun.COM void 815*11963SAfshin.Ardakani@Sun.COM smb_slist_wait_for_empty( 816*11963SAfshin.Ardakani@Sun.COM smb_slist_t *sl) 817*11963SAfshin.Ardakani@Sun.COM { 818*11963SAfshin.Ardakani@Sun.COM mutex_enter(&sl->sl_mutex); 819*11963SAfshin.Ardakani@Sun.COM while (sl->sl_count) { 820*11963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_TRUE; 821*11963SAfshin.Ardakani@Sun.COM cv_wait(&sl->sl_cv, &sl->sl_mutex); 822*11963SAfshin.Ardakani@Sun.COM } 823*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 824*11963SAfshin.Ardakani@Sun.COM } 825*11963SAfshin.Ardakani@Sun.COM 826*11963SAfshin.Ardakani@Sun.COM /* 827*11963SAfshin.Ardakani@Sun.COM * smb_slist_exit 828*11963SAfshin.Ardakani@Sun.COM * 829*11963SAfshin.Ardakani@Sun.COM * This function exits the muetx of the list and signal the condition variable 830*11963SAfshin.Ardakani@Sun.COM * if the list is empty. 831*11963SAfshin.Ardakani@Sun.COM */ 832*11963SAfshin.Ardakani@Sun.COM void 833*11963SAfshin.Ardakani@Sun.COM smb_slist_exit(smb_slist_t *sl) 834*11963SAfshin.Ardakani@Sun.COM { 835*11963SAfshin.Ardakani@Sun.COM if ((sl->sl_count == 0) && (sl->sl_waiting)) { 836*11963SAfshin.Ardakani@Sun.COM sl->sl_waiting = B_FALSE; 837*11963SAfshin.Ardakani@Sun.COM cv_broadcast(&sl->sl_cv); 838*11963SAfshin.Ardakani@Sun.COM } 839*11963SAfshin.Ardakani@Sun.COM mutex_exit(&sl->sl_mutex); 840*11963SAfshin.Ardakani@Sun.COM } 841*11963SAfshin.Ardakani@Sun.COM 842*11963SAfshin.Ardakani@Sun.COM /* 843*11963SAfshin.Ardakani@Sun.COM * smb_thread_entry_point 844*11963SAfshin.Ardakani@Sun.COM * 845*11963SAfshin.Ardakani@Sun.COM * Common entry point for all the threads created through smb_thread_start. 846*11963SAfshin.Ardakani@Sun.COM * The state of the thread is set to "running" at the beginning and moved to 847*11963SAfshin.Ardakani@Sun.COM * "exiting" just before calling thread_exit(). The condition variable is 848*11963SAfshin.Ardakani@Sun.COM * also signaled. 849*11963SAfshin.Ardakani@Sun.COM */ 850*11963SAfshin.Ardakani@Sun.COM static void 851*11963SAfshin.Ardakani@Sun.COM smb_thread_entry_point( 852*11963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 853*11963SAfshin.Ardakani@Sun.COM { 854*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 855*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 856*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_state == SMB_THREAD_STATE_STARTING); 857*11963SAfshin.Ardakani@Sun.COM thread->sth_th = curthread; 858*11963SAfshin.Ardakani@Sun.COM thread->sth_did = thread->sth_th->t_did; 859*11963SAfshin.Ardakani@Sun.COM 860*11963SAfshin.Ardakani@Sun.COM if (!thread->sth_kill) { 861*11963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_RUNNING; 862*11963SAfshin.Ardakani@Sun.COM cv_signal(&thread->sth_cv); 863*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 864*11963SAfshin.Ardakani@Sun.COM thread->sth_ep(thread, thread->sth_ep_arg); 865*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 866*11963SAfshin.Ardakani@Sun.COM } 867*11963SAfshin.Ardakani@Sun.COM thread->sth_th = NULL; 868*11963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITING; 869*11963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv); 870*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 871*11963SAfshin.Ardakani@Sun.COM thread_exit(); 872*11963SAfshin.Ardakani@Sun.COM } 873*11963SAfshin.Ardakani@Sun.COM 874*11963SAfshin.Ardakani@Sun.COM /* 875*11963SAfshin.Ardakani@Sun.COM * smb_thread_init 876*11963SAfshin.Ardakani@Sun.COM */ 877*11963SAfshin.Ardakani@Sun.COM void 878*11963SAfshin.Ardakani@Sun.COM smb_thread_init( 879*11963SAfshin.Ardakani@Sun.COM smb_thread_t *thread, 880*11963SAfshin.Ardakani@Sun.COM char *name, 881*11963SAfshin.Ardakani@Sun.COM smb_thread_ep_t ep, 882*11963SAfshin.Ardakani@Sun.COM void *ep_arg, 883*11963SAfshin.Ardakani@Sun.COM smb_thread_aw_t aw, 884*11963SAfshin.Ardakani@Sun.COM void *aw_arg) 885*11963SAfshin.Ardakani@Sun.COM { 886*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic != SMB_THREAD_MAGIC); 887*11963SAfshin.Ardakani@Sun.COM 888*11963SAfshin.Ardakani@Sun.COM bzero(thread, sizeof (*thread)); 889*11963SAfshin.Ardakani@Sun.COM 890*11963SAfshin.Ardakani@Sun.COM (void) strlcpy(thread->sth_name, name, sizeof (thread->sth_name)); 891*11963SAfshin.Ardakani@Sun.COM thread->sth_ep = ep; 892*11963SAfshin.Ardakani@Sun.COM thread->sth_ep_arg = ep_arg; 893*11963SAfshin.Ardakani@Sun.COM thread->sth_aw = aw; 894*11963SAfshin.Ardakani@Sun.COM thread->sth_aw_arg = aw_arg; 895*11963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED; 896*11963SAfshin.Ardakani@Sun.COM mutex_init(&thread->sth_mtx, NULL, MUTEX_DEFAULT, NULL); 897*11963SAfshin.Ardakani@Sun.COM cv_init(&thread->sth_cv, NULL, CV_DEFAULT, NULL); 898*11963SAfshin.Ardakani@Sun.COM thread->sth_magic = SMB_THREAD_MAGIC; 899*11963SAfshin.Ardakani@Sun.COM } 900*11963SAfshin.Ardakani@Sun.COM 901*11963SAfshin.Ardakani@Sun.COM /* 902*11963SAfshin.Ardakani@Sun.COM * smb_thread_destroy 903*11963SAfshin.Ardakani@Sun.COM */ 904*11963SAfshin.Ardakani@Sun.COM void 905*11963SAfshin.Ardakani@Sun.COM smb_thread_destroy( 906*11963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 907*11963SAfshin.Ardakani@Sun.COM { 908*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 909*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_state == SMB_THREAD_STATE_EXITED); 910*11963SAfshin.Ardakani@Sun.COM thread->sth_magic = 0; 911*11963SAfshin.Ardakani@Sun.COM mutex_destroy(&thread->sth_mtx); 912*11963SAfshin.Ardakani@Sun.COM cv_destroy(&thread->sth_cv); 913*11963SAfshin.Ardakani@Sun.COM } 914*11963SAfshin.Ardakani@Sun.COM 915*11963SAfshin.Ardakani@Sun.COM /* 916*11963SAfshin.Ardakani@Sun.COM * smb_thread_start 917*11963SAfshin.Ardakani@Sun.COM * 918*11963SAfshin.Ardakani@Sun.COM * This function starts a thread with the parameters provided. It waits until 919*11963SAfshin.Ardakani@Sun.COM * the state of the thread has been moved to running. 920*11963SAfshin.Ardakani@Sun.COM */ 921*11963SAfshin.Ardakani@Sun.COM /*ARGSUSED*/ 922*11963SAfshin.Ardakani@Sun.COM int 923*11963SAfshin.Ardakani@Sun.COM smb_thread_start( 924*11963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 925*11963SAfshin.Ardakani@Sun.COM { 926*11963SAfshin.Ardakani@Sun.COM int rc = 0; 927*11963SAfshin.Ardakani@Sun.COM kthread_t *tmpthread; 928*11963SAfshin.Ardakani@Sun.COM 929*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 930*11963SAfshin.Ardakani@Sun.COM 931*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 932*11963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) { 933*11963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITED: 934*11963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_STARTING; 935*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 936*11963SAfshin.Ardakani@Sun.COM tmpthread = thread_create(NULL, 0, smb_thread_entry_point, 937*11963SAfshin.Ardakani@Sun.COM thread, 0, &p0, TS_RUN, minclsyspri); 938*11963SAfshin.Ardakani@Sun.COM ASSERT(tmpthread != NULL); 939*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 940*11963SAfshin.Ardakani@Sun.COM while (thread->sth_state == SMB_THREAD_STATE_STARTING) 941*11963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 942*11963SAfshin.Ardakani@Sun.COM if (thread->sth_state != SMB_THREAD_STATE_RUNNING) 943*11963SAfshin.Ardakani@Sun.COM rc = -1; 944*11963SAfshin.Ardakani@Sun.COM break; 945*11963SAfshin.Ardakani@Sun.COM default: 946*11963SAfshin.Ardakani@Sun.COM ASSERT(0); 947*11963SAfshin.Ardakani@Sun.COM rc = -1; 948*11963SAfshin.Ardakani@Sun.COM break; 949*11963SAfshin.Ardakani@Sun.COM } 950*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 951*11963SAfshin.Ardakani@Sun.COM return (rc); 952*11963SAfshin.Ardakani@Sun.COM } 953*11963SAfshin.Ardakani@Sun.COM 954*11963SAfshin.Ardakani@Sun.COM /* 955*11963SAfshin.Ardakani@Sun.COM * smb_thread_stop 956*11963SAfshin.Ardakani@Sun.COM * 957*11963SAfshin.Ardakani@Sun.COM * This function signals a thread to kill itself and waits until the "exiting" 958*11963SAfshin.Ardakani@Sun.COM * state has been reached. 959*11963SAfshin.Ardakani@Sun.COM */ 960*11963SAfshin.Ardakani@Sun.COM void 961*11963SAfshin.Ardakani@Sun.COM smb_thread_stop( 962*11963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 963*11963SAfshin.Ardakani@Sun.COM { 964*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 965*11963SAfshin.Ardakani@Sun.COM 966*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 967*11963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) { 968*11963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_RUNNING: 969*11963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_STARTING: 970*11963SAfshin.Ardakani@Sun.COM if (!thread->sth_kill) { 971*11963SAfshin.Ardakani@Sun.COM thread->sth_kill = B_TRUE; 972*11963SAfshin.Ardakani@Sun.COM if (thread->sth_aw) 973*11963SAfshin.Ardakani@Sun.COM thread->sth_aw(thread, thread->sth_aw_arg); 974*11963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv); 975*11963SAfshin.Ardakani@Sun.COM while (thread->sth_state != SMB_THREAD_STATE_EXITING) 976*11963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 977*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 978*11963SAfshin.Ardakani@Sun.COM thread_join(thread->sth_did); 979*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 980*11963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED; 981*11963SAfshin.Ardakani@Sun.COM thread->sth_did = 0; 982*11963SAfshin.Ardakani@Sun.COM thread->sth_kill = B_FALSE; 983*11963SAfshin.Ardakani@Sun.COM cv_broadcast(&thread->sth_cv); 984*11963SAfshin.Ardakani@Sun.COM break; 985*11963SAfshin.Ardakani@Sun.COM } 986*11963SAfshin.Ardakani@Sun.COM /*FALLTHRU*/ 987*11963SAfshin.Ardakani@Sun.COM 988*11963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITING: 989*11963SAfshin.Ardakani@Sun.COM if (thread->sth_kill) { 990*11963SAfshin.Ardakani@Sun.COM while (thread->sth_state != SMB_THREAD_STATE_EXITED) 991*11963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 992*11963SAfshin.Ardakani@Sun.COM } else { 993*11963SAfshin.Ardakani@Sun.COM thread->sth_state = SMB_THREAD_STATE_EXITED; 994*11963SAfshin.Ardakani@Sun.COM thread->sth_did = 0; 995*11963SAfshin.Ardakani@Sun.COM } 996*11963SAfshin.Ardakani@Sun.COM break; 997*11963SAfshin.Ardakani@Sun.COM 998*11963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_EXITED: 999*11963SAfshin.Ardakani@Sun.COM break; 1000*11963SAfshin.Ardakani@Sun.COM 1001*11963SAfshin.Ardakani@Sun.COM default: 1002*11963SAfshin.Ardakani@Sun.COM ASSERT(0); 1003*11963SAfshin.Ardakani@Sun.COM break; 1004*11963SAfshin.Ardakani@Sun.COM } 1005*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 1006*11963SAfshin.Ardakani@Sun.COM } 1007*11963SAfshin.Ardakani@Sun.COM 1008*11963SAfshin.Ardakani@Sun.COM /* 1009*11963SAfshin.Ardakani@Sun.COM * smb_thread_signal 1010*11963SAfshin.Ardakani@Sun.COM * 1011*11963SAfshin.Ardakani@Sun.COM * This function signals a thread. 1012*11963SAfshin.Ardakani@Sun.COM */ 1013*11963SAfshin.Ardakani@Sun.COM void 1014*11963SAfshin.Ardakani@Sun.COM smb_thread_signal( 1015*11963SAfshin.Ardakani@Sun.COM smb_thread_t *thread) 1016*11963SAfshin.Ardakani@Sun.COM { 1017*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1018*11963SAfshin.Ardakani@Sun.COM 1019*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 1020*11963SAfshin.Ardakani@Sun.COM switch (thread->sth_state) { 1021*11963SAfshin.Ardakani@Sun.COM case SMB_THREAD_STATE_RUNNING: 1022*11963SAfshin.Ardakani@Sun.COM if (thread->sth_aw) 1023*11963SAfshin.Ardakani@Sun.COM thread->sth_aw(thread, thread->sth_aw_arg); 1024*11963SAfshin.Ardakani@Sun.COM cv_signal(&thread->sth_cv); 1025*11963SAfshin.Ardakani@Sun.COM break; 1026*11963SAfshin.Ardakani@Sun.COM 1027*11963SAfshin.Ardakani@Sun.COM default: 1028*11963SAfshin.Ardakani@Sun.COM break; 1029*11963SAfshin.Ardakani@Sun.COM } 1030*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 1031*11963SAfshin.Ardakani@Sun.COM } 1032*11963SAfshin.Ardakani@Sun.COM 1033*11963SAfshin.Ardakani@Sun.COM boolean_t 1034*11963SAfshin.Ardakani@Sun.COM smb_thread_continue(smb_thread_t *thread) 1035*11963SAfshin.Ardakani@Sun.COM { 1036*11963SAfshin.Ardakani@Sun.COM boolean_t result; 1037*11963SAfshin.Ardakani@Sun.COM 1038*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1039*11963SAfshin.Ardakani@Sun.COM 1040*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 1041*11963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, 0); 1042*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 1043*11963SAfshin.Ardakani@Sun.COM 1044*11963SAfshin.Ardakani@Sun.COM return (result); 1045*11963SAfshin.Ardakani@Sun.COM } 1046*11963SAfshin.Ardakani@Sun.COM 1047*11963SAfshin.Ardakani@Sun.COM boolean_t 1048*11963SAfshin.Ardakani@Sun.COM smb_thread_continue_nowait(smb_thread_t *thread) 1049*11963SAfshin.Ardakani@Sun.COM { 1050*11963SAfshin.Ardakani@Sun.COM boolean_t result; 1051*11963SAfshin.Ardakani@Sun.COM 1052*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1053*11963SAfshin.Ardakani@Sun.COM 1054*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 1055*11963SAfshin.Ardakani@Sun.COM /* 1056*11963SAfshin.Ardakani@Sun.COM * Setting ticks=-1 requests a non-blocking check. We will 1057*11963SAfshin.Ardakani@Sun.COM * still block if the thread is in "suspend" state. 1058*11963SAfshin.Ardakani@Sun.COM */ 1059*11963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, -1); 1060*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 1061*11963SAfshin.Ardakani@Sun.COM 1062*11963SAfshin.Ardakani@Sun.COM return (result); 1063*11963SAfshin.Ardakani@Sun.COM } 1064*11963SAfshin.Ardakani@Sun.COM 1065*11963SAfshin.Ardakani@Sun.COM boolean_t 1066*11963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait(smb_thread_t *thread, int seconds) 1067*11963SAfshin.Ardakani@Sun.COM { 1068*11963SAfshin.Ardakani@Sun.COM boolean_t result; 1069*11963SAfshin.Ardakani@Sun.COM 1070*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1071*11963SAfshin.Ardakani@Sun.COM 1072*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 1073*11963SAfshin.Ardakani@Sun.COM result = smb_thread_continue_timedwait_locked(thread, 1074*11963SAfshin.Ardakani@Sun.COM SEC_TO_TICK(seconds)); 1075*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 1076*11963SAfshin.Ardakani@Sun.COM 1077*11963SAfshin.Ardakani@Sun.COM return (result); 1078*11963SAfshin.Ardakani@Sun.COM } 1079*11963SAfshin.Ardakani@Sun.COM 1080*11963SAfshin.Ardakani@Sun.COM /* 1081*11963SAfshin.Ardakani@Sun.COM * smb_thread_continue_timedwait_locked 1082*11963SAfshin.Ardakani@Sun.COM * 1083*11963SAfshin.Ardakani@Sun.COM * Internal only. Ticks==-1 means don't block, Ticks == 0 means wait 1084*11963SAfshin.Ardakani@Sun.COM * indefinitely 1085*11963SAfshin.Ardakani@Sun.COM */ 1086*11963SAfshin.Ardakani@Sun.COM static boolean_t 1087*11963SAfshin.Ardakani@Sun.COM smb_thread_continue_timedwait_locked(smb_thread_t *thread, int ticks) 1088*11963SAfshin.Ardakani@Sun.COM { 1089*11963SAfshin.Ardakani@Sun.COM boolean_t result; 1090*11963SAfshin.Ardakani@Sun.COM 1091*11963SAfshin.Ardakani@Sun.COM /* -1 means don't block */ 1092*11963SAfshin.Ardakani@Sun.COM if (ticks != -1 && !thread->sth_kill) { 1093*11963SAfshin.Ardakani@Sun.COM if (ticks == 0) { 1094*11963SAfshin.Ardakani@Sun.COM cv_wait(&thread->sth_cv, &thread->sth_mtx); 1095*11963SAfshin.Ardakani@Sun.COM } else { 1096*11963SAfshin.Ardakani@Sun.COM (void) cv_reltimedwait(&thread->sth_cv, 1097*11963SAfshin.Ardakani@Sun.COM &thread->sth_mtx, (clock_t)ticks, TR_CLOCK_TICK); 1098*11963SAfshin.Ardakani@Sun.COM } 1099*11963SAfshin.Ardakani@Sun.COM } 1100*11963SAfshin.Ardakani@Sun.COM result = (thread->sth_kill == 0); 1101*11963SAfshin.Ardakani@Sun.COM 1102*11963SAfshin.Ardakani@Sun.COM return (result); 1103*11963SAfshin.Ardakani@Sun.COM } 1104*11963SAfshin.Ardakani@Sun.COM 1105*11963SAfshin.Ardakani@Sun.COM void 1106*11963SAfshin.Ardakani@Sun.COM smb_thread_set_awaken(smb_thread_t *thread, smb_thread_aw_t new_aw_fn, 1107*11963SAfshin.Ardakani@Sun.COM void *new_aw_arg) 1108*11963SAfshin.Ardakani@Sun.COM { 1109*11963SAfshin.Ardakani@Sun.COM ASSERT(thread->sth_magic == SMB_THREAD_MAGIC); 1110*11963SAfshin.Ardakani@Sun.COM 1111*11963SAfshin.Ardakani@Sun.COM mutex_enter(&thread->sth_mtx); 1112*11963SAfshin.Ardakani@Sun.COM thread->sth_aw = new_aw_fn; 1113*11963SAfshin.Ardakani@Sun.COM thread->sth_aw_arg = new_aw_arg; 1114*11963SAfshin.Ardakani@Sun.COM mutex_exit(&thread->sth_mtx); 1115*11963SAfshin.Ardakani@Sun.COM } 1116*11963SAfshin.Ardakani@Sun.COM 1117*11963SAfshin.Ardakani@Sun.COM /* 1118*11963SAfshin.Ardakani@Sun.COM * smb_rwx_init 1119*11963SAfshin.Ardakani@Sun.COM */ 1120*11963SAfshin.Ardakani@Sun.COM void 1121*11963SAfshin.Ardakani@Sun.COM smb_rwx_init( 1122*11963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 1123*11963SAfshin.Ardakani@Sun.COM { 1124*11963SAfshin.Ardakani@Sun.COM bzero(rwx, sizeof (smb_rwx_t)); 1125*11963SAfshin.Ardakani@Sun.COM cv_init(&rwx->rwx_cv, NULL, CV_DEFAULT, NULL); 1126*11963SAfshin.Ardakani@Sun.COM mutex_init(&rwx->rwx_mutex, NULL, MUTEX_DEFAULT, NULL); 1127*11963SAfshin.Ardakani@Sun.COM rw_init(&rwx->rwx_lock, NULL, RW_DEFAULT, NULL); 1128*11963SAfshin.Ardakani@Sun.COM } 1129*11963SAfshin.Ardakani@Sun.COM 1130*11963SAfshin.Ardakani@Sun.COM /* 1131*11963SAfshin.Ardakani@Sun.COM * smb_rwx_destroy 1132*11963SAfshin.Ardakani@Sun.COM */ 1133*11963SAfshin.Ardakani@Sun.COM void 1134*11963SAfshin.Ardakani@Sun.COM smb_rwx_destroy( 1135*11963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 1136*11963SAfshin.Ardakani@Sun.COM { 1137*11963SAfshin.Ardakani@Sun.COM mutex_destroy(&rwx->rwx_mutex); 1138*11963SAfshin.Ardakani@Sun.COM cv_destroy(&rwx->rwx_cv); 1139*11963SAfshin.Ardakani@Sun.COM rw_destroy(&rwx->rwx_lock); 1140*11963SAfshin.Ardakani@Sun.COM } 1141*11963SAfshin.Ardakani@Sun.COM 1142*11963SAfshin.Ardakani@Sun.COM /* 1143*11963SAfshin.Ardakani@Sun.COM * smb_rwx_rwexit 1144*11963SAfshin.Ardakani@Sun.COM */ 1145*11963SAfshin.Ardakani@Sun.COM void 1146*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwexit( 1147*11963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 1148*11963SAfshin.Ardakani@Sun.COM { 1149*11963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) { 1150*11963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 1151*11963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 1152*11963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) { 1153*11963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_FALSE; 1154*11963SAfshin.Ardakani@Sun.COM cv_broadcast(&rwx->rwx_cv); 1155*11963SAfshin.Ardakani@Sun.COM } 1156*11963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 1157*11963SAfshin.Ardakani@Sun.COM } 1158*11963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock); 1159*11963SAfshin.Ardakani@Sun.COM } 1160*11963SAfshin.Ardakani@Sun.COM 1161*11963SAfshin.Ardakani@Sun.COM /* 1162*11963SAfshin.Ardakani@Sun.COM * smb_rwx_rwupgrade 1163*11963SAfshin.Ardakani@Sun.COM */ 1164*11963SAfshin.Ardakani@Sun.COM krw_t 1165*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwupgrade( 1166*11963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx) 1167*11963SAfshin.Ardakani@Sun.COM { 1168*11963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) { 1169*11963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 1170*11963SAfshin.Ardakani@Sun.COM return (RW_WRITER); 1171*11963SAfshin.Ardakani@Sun.COM } 1172*11963SAfshin.Ardakani@Sun.COM if (!rw_tryupgrade(&rwx->rwx_lock)) { 1173*11963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock); 1174*11963SAfshin.Ardakani@Sun.COM rw_enter(&rwx->rwx_lock, RW_WRITER); 1175*11963SAfshin.Ardakani@Sun.COM } 1176*11963SAfshin.Ardakani@Sun.COM return (RW_READER); 1177*11963SAfshin.Ardakani@Sun.COM } 1178*11963SAfshin.Ardakani@Sun.COM 1179*11963SAfshin.Ardakani@Sun.COM /* 1180*11963SAfshin.Ardakani@Sun.COM * smb_rwx_rwrestore 1181*11963SAfshin.Ardakani@Sun.COM */ 1182*11963SAfshin.Ardakani@Sun.COM void 1183*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwdowngrade( 1184*11963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx, 1185*11963SAfshin.Ardakani@Sun.COM krw_t mode) 1186*11963SAfshin.Ardakani@Sun.COM { 1187*11963SAfshin.Ardakani@Sun.COM ASSERT(rw_write_held(&rwx->rwx_lock)); 1188*11963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 1189*11963SAfshin.Ardakani@Sun.COM 1190*11963SAfshin.Ardakani@Sun.COM if (mode == RW_WRITER) { 1191*11963SAfshin.Ardakani@Sun.COM return; 1192*11963SAfshin.Ardakani@Sun.COM } 1193*11963SAfshin.Ardakani@Sun.COM ASSERT(mode == RW_READER); 1194*11963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 1195*11963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) { 1196*11963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_FALSE; 1197*11963SAfshin.Ardakani@Sun.COM cv_broadcast(&rwx->rwx_cv); 1198*11963SAfshin.Ardakani@Sun.COM } 1199*11963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 1200*11963SAfshin.Ardakani@Sun.COM rw_downgrade(&rwx->rwx_lock); 1201*11963SAfshin.Ardakani@Sun.COM } 1202*11963SAfshin.Ardakani@Sun.COM 1203*11963SAfshin.Ardakani@Sun.COM /* 1204*11963SAfshin.Ardakani@Sun.COM * smb_rwx_wait 1205*11963SAfshin.Ardakani@Sun.COM * 1206*11963SAfshin.Ardakani@Sun.COM * This function assumes the smb_rwx lock was enter in RW_READER or RW_WRITER 1207*11963SAfshin.Ardakani@Sun.COM * mode. It will: 1208*11963SAfshin.Ardakani@Sun.COM * 1209*11963SAfshin.Ardakani@Sun.COM * 1) release the lock and save its current mode. 1210*11963SAfshin.Ardakani@Sun.COM * 2) wait until the condition variable is signaled. This can happen for 1211*11963SAfshin.Ardakani@Sun.COM * 2 reasons: When a writer releases the lock or when the time out (if 1212*11963SAfshin.Ardakani@Sun.COM * provided) expires. 1213*11963SAfshin.Ardakani@Sun.COM * 3) re-acquire the lock in the mode saved in (1). 1214*11963SAfshin.Ardakani@Sun.COM */ 1215*11963SAfshin.Ardakani@Sun.COM int 1216*11963SAfshin.Ardakani@Sun.COM smb_rwx_rwwait( 1217*11963SAfshin.Ardakani@Sun.COM smb_rwx_t *rwx, 1218*11963SAfshin.Ardakani@Sun.COM clock_t timeout) 1219*11963SAfshin.Ardakani@Sun.COM { 1220*11963SAfshin.Ardakani@Sun.COM int rc; 1221*11963SAfshin.Ardakani@Sun.COM krw_t mode; 1222*11963SAfshin.Ardakani@Sun.COM 1223*11963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 1224*11963SAfshin.Ardakani@Sun.COM rwx->rwx_waiting = B_TRUE; 1225*11963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 1226*11963SAfshin.Ardakani@Sun.COM 1227*11963SAfshin.Ardakani@Sun.COM if (rw_write_held(&rwx->rwx_lock)) { 1228*11963SAfshin.Ardakani@Sun.COM ASSERT(rw_owner(&rwx->rwx_lock) == curthread); 1229*11963SAfshin.Ardakani@Sun.COM mode = RW_WRITER; 1230*11963SAfshin.Ardakani@Sun.COM } else { 1231*11963SAfshin.Ardakani@Sun.COM ASSERT(rw_read_held(&rwx->rwx_lock)); 1232*11963SAfshin.Ardakani@Sun.COM mode = RW_READER; 1233*11963SAfshin.Ardakani@Sun.COM } 1234*11963SAfshin.Ardakani@Sun.COM rw_exit(&rwx->rwx_lock); 1235*11963SAfshin.Ardakani@Sun.COM 1236*11963SAfshin.Ardakani@Sun.COM mutex_enter(&rwx->rwx_mutex); 1237*11963SAfshin.Ardakani@Sun.COM if (rwx->rwx_waiting) { 1238*11963SAfshin.Ardakani@Sun.COM if (timeout == -1) { 1239*11963SAfshin.Ardakani@Sun.COM rc = 1; 1240*11963SAfshin.Ardakani@Sun.COM cv_wait(&rwx->rwx_cv, &rwx->rwx_mutex); 1241*11963SAfshin.Ardakani@Sun.COM } else { 1242*11963SAfshin.Ardakani@Sun.COM rc = cv_reltimedwait(&rwx->rwx_cv, &rwx->rwx_mutex, 1243*11963SAfshin.Ardakani@Sun.COM timeout, TR_CLOCK_TICK); 1244*11963SAfshin.Ardakani@Sun.COM } 1245*11963SAfshin.Ardakani@Sun.COM } 1246*11963SAfshin.Ardakani@Sun.COM mutex_exit(&rwx->rwx_mutex); 1247*11963SAfshin.Ardakani@Sun.COM 1248*11963SAfshin.Ardakani@Sun.COM rw_enter(&rwx->rwx_lock, mode); 1249*11963SAfshin.Ardakani@Sun.COM return (rc); 1250*11963SAfshin.Ardakani@Sun.COM } 1251*11963SAfshin.Ardakani@Sun.COM 1252*11963SAfshin.Ardakani@Sun.COM /* 1253*11963SAfshin.Ardakani@Sun.COM * SMB ID mapping 1254*11963SAfshin.Ardakani@Sun.COM * 1255*11963SAfshin.Ardakani@Sun.COM * Solaris ID mapping service (aka Winchester) works with domain SIDs 1256*11963SAfshin.Ardakani@Sun.COM * and RIDs where domain SIDs are in string format. CIFS service works 1257*11963SAfshin.Ardakani@Sun.COM * with binary SIDs understandable by CIFS clients. A layer of SMB ID 1258*11963SAfshin.Ardakani@Sun.COM * mapping functions are implemeted to hide the SID conversion details 1259*11963SAfshin.Ardakani@Sun.COM * and also hide the handling of array of batch mapping requests. 1260*11963SAfshin.Ardakani@Sun.COM * 1261*11963SAfshin.Ardakani@Sun.COM * IMPORTANT NOTE The Winchester API requires a zone. Because CIFS server 1262*11963SAfshin.Ardakani@Sun.COM * currently only runs in the global zone the global zone is specified. 1263*11963SAfshin.Ardakani@Sun.COM * This needs to be fixed when the CIFS server supports zones. 1264*11963SAfshin.Ardakani@Sun.COM */ 1265*11963SAfshin.Ardakani@Sun.COM 1266*11963SAfshin.Ardakani@Sun.COM static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib); 1267*11963SAfshin.Ardakani@Sun.COM 1268*11963SAfshin.Ardakani@Sun.COM /* 1269*11963SAfshin.Ardakani@Sun.COM * smb_idmap_getid 1270*11963SAfshin.Ardakani@Sun.COM * 1271*11963SAfshin.Ardakani@Sun.COM * Maps the given Windows SID to a Solaris ID using the 1272*11963SAfshin.Ardakani@Sun.COM * simple mapping API. 1273*11963SAfshin.Ardakani@Sun.COM */ 1274*11963SAfshin.Ardakani@Sun.COM idmap_stat 1275*11963SAfshin.Ardakani@Sun.COM smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype) 1276*11963SAfshin.Ardakani@Sun.COM { 1277*11963SAfshin.Ardakani@Sun.COM smb_idmap_t sim; 1278*11963SAfshin.Ardakani@Sun.COM char sidstr[SMB_SID_STRSZ]; 1279*11963SAfshin.Ardakani@Sun.COM 1280*11963SAfshin.Ardakani@Sun.COM smb_sid_tostr(sid, sidstr); 1281*11963SAfshin.Ardakani@Sun.COM if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0) 1282*11963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_SID); 1283*11963SAfshin.Ardakani@Sun.COM sim.sim_domsid = sidstr; 1284*11963SAfshin.Ardakani@Sun.COM sim.sim_id = id; 1285*11963SAfshin.Ardakani@Sun.COM 1286*11963SAfshin.Ardakani@Sun.COM switch (*idtype) { 1287*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 1288*11963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid, 1289*11963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id); 1290*11963SAfshin.Ardakani@Sun.COM break; 1291*11963SAfshin.Ardakani@Sun.COM 1292*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 1293*11963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid, 1294*11963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id); 1295*11963SAfshin.Ardakani@Sun.COM break; 1296*11963SAfshin.Ardakani@Sun.COM 1297*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_UNKNOWN: 1298*11963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid, 1299*11963SAfshin.Ardakani@Sun.COM sim.sim_rid, sim.sim_id, &sim.sim_idtype); 1300*11963SAfshin.Ardakani@Sun.COM break; 1301*11963SAfshin.Ardakani@Sun.COM 1302*11963SAfshin.Ardakani@Sun.COM default: 1303*11963SAfshin.Ardakani@Sun.COM ASSERT(0); 1304*11963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 1305*11963SAfshin.Ardakani@Sun.COM } 1306*11963SAfshin.Ardakani@Sun.COM 1307*11963SAfshin.Ardakani@Sun.COM *idtype = sim.sim_idtype; 1308*11963SAfshin.Ardakani@Sun.COM 1309*11963SAfshin.Ardakani@Sun.COM return (sim.sim_stat); 1310*11963SAfshin.Ardakani@Sun.COM } 1311*11963SAfshin.Ardakani@Sun.COM 1312*11963SAfshin.Ardakani@Sun.COM /* 1313*11963SAfshin.Ardakani@Sun.COM * smb_idmap_getsid 1314*11963SAfshin.Ardakani@Sun.COM * 1315*11963SAfshin.Ardakani@Sun.COM * Maps the given Solaris ID to a Windows SID using the 1316*11963SAfshin.Ardakani@Sun.COM * simple mapping API. 1317*11963SAfshin.Ardakani@Sun.COM */ 1318*11963SAfshin.Ardakani@Sun.COM idmap_stat 1319*11963SAfshin.Ardakani@Sun.COM smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid) 1320*11963SAfshin.Ardakani@Sun.COM { 1321*11963SAfshin.Ardakani@Sun.COM smb_idmap_t sim; 1322*11963SAfshin.Ardakani@Sun.COM 1323*11963SAfshin.Ardakani@Sun.COM switch (idtype) { 1324*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 1325*11963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getsidbyuid(global_zone, id, 1326*11963SAfshin.Ardakani@Sun.COM (const char **)&sim.sim_domsid, &sim.sim_rid); 1327*11963SAfshin.Ardakani@Sun.COM break; 1328*11963SAfshin.Ardakani@Sun.COM 1329*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 1330*11963SAfshin.Ardakani@Sun.COM sim.sim_stat = kidmap_getsidbygid(global_zone, id, 1331*11963SAfshin.Ardakani@Sun.COM (const char **)&sim.sim_domsid, &sim.sim_rid); 1332*11963SAfshin.Ardakani@Sun.COM break; 1333*11963SAfshin.Ardakani@Sun.COM 1334*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_EVERYONE: 1335*11963SAfshin.Ardakani@Sun.COM /* Everyone S-1-1-0 */ 1336*11963SAfshin.Ardakani@Sun.COM sim.sim_domsid = "S-1-1"; 1337*11963SAfshin.Ardakani@Sun.COM sim.sim_rid = 0; 1338*11963SAfshin.Ardakani@Sun.COM sim.sim_stat = IDMAP_SUCCESS; 1339*11963SAfshin.Ardakani@Sun.COM break; 1340*11963SAfshin.Ardakani@Sun.COM 1341*11963SAfshin.Ardakani@Sun.COM default: 1342*11963SAfshin.Ardakani@Sun.COM ASSERT(0); 1343*11963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 1344*11963SAfshin.Ardakani@Sun.COM } 1345*11963SAfshin.Ardakani@Sun.COM 1346*11963SAfshin.Ardakani@Sun.COM if (sim.sim_stat != IDMAP_SUCCESS) 1347*11963SAfshin.Ardakani@Sun.COM return (sim.sim_stat); 1348*11963SAfshin.Ardakani@Sun.COM 1349*11963SAfshin.Ardakani@Sun.COM if (sim.sim_domsid == NULL) 1350*11963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_NOMAPPING); 1351*11963SAfshin.Ardakani@Sun.COM 1352*11963SAfshin.Ardakani@Sun.COM sim.sim_sid = smb_sid_fromstr(sim.sim_domsid); 1353*11963SAfshin.Ardakani@Sun.COM if (sim.sim_sid == NULL) 1354*11963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_INTERNAL); 1355*11963SAfshin.Ardakani@Sun.COM 1356*11963SAfshin.Ardakani@Sun.COM *sid = smb_sid_splice(sim.sim_sid, sim.sim_rid); 1357*11963SAfshin.Ardakani@Sun.COM smb_sid_free(sim.sim_sid); 1358*11963SAfshin.Ardakani@Sun.COM if (*sid == NULL) 1359*11963SAfshin.Ardakani@Sun.COM sim.sim_stat = IDMAP_ERR_INTERNAL; 1360*11963SAfshin.Ardakani@Sun.COM 1361*11963SAfshin.Ardakani@Sun.COM return (sim.sim_stat); 1362*11963SAfshin.Ardakani@Sun.COM } 1363*11963SAfshin.Ardakani@Sun.COM 1364*11963SAfshin.Ardakani@Sun.COM /* 1365*11963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_create 1366*11963SAfshin.Ardakani@Sun.COM * 1367*11963SAfshin.Ardakani@Sun.COM * Creates and initializes the context for batch ID mapping. 1368*11963SAfshin.Ardakani@Sun.COM */ 1369*11963SAfshin.Ardakani@Sun.COM idmap_stat 1370*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags) 1371*11963SAfshin.Ardakani@Sun.COM { 1372*11963SAfshin.Ardakani@Sun.COM ASSERT(sib); 1373*11963SAfshin.Ardakani@Sun.COM 1374*11963SAfshin.Ardakani@Sun.COM bzero(sib, sizeof (smb_idmap_batch_t)); 1375*11963SAfshin.Ardakani@Sun.COM 1376*11963SAfshin.Ardakani@Sun.COM sib->sib_idmaph = kidmap_get_create(global_zone); 1377*11963SAfshin.Ardakani@Sun.COM 1378*11963SAfshin.Ardakani@Sun.COM sib->sib_flags = flags; 1379*11963SAfshin.Ardakani@Sun.COM sib->sib_nmap = nmap; 1380*11963SAfshin.Ardakani@Sun.COM sib->sib_size = nmap * sizeof (smb_idmap_t); 1381*11963SAfshin.Ardakani@Sun.COM sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP); 1382*11963SAfshin.Ardakani@Sun.COM 1383*11963SAfshin.Ardakani@Sun.COM return (IDMAP_SUCCESS); 1384*11963SAfshin.Ardakani@Sun.COM } 1385*11963SAfshin.Ardakani@Sun.COM 1386*11963SAfshin.Ardakani@Sun.COM /* 1387*11963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_destroy 1388*11963SAfshin.Ardakani@Sun.COM * 1389*11963SAfshin.Ardakani@Sun.COM * Frees the batch ID mapping context. 1390*11963SAfshin.Ardakani@Sun.COM * If ID mapping is Solaris -> Windows it frees memories 1391*11963SAfshin.Ardakani@Sun.COM * allocated for binary SIDs. 1392*11963SAfshin.Ardakani@Sun.COM */ 1393*11963SAfshin.Ardakani@Sun.COM void 1394*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_destroy(smb_idmap_batch_t *sib) 1395*11963SAfshin.Ardakani@Sun.COM { 1396*11963SAfshin.Ardakani@Sun.COM char *domsid; 1397*11963SAfshin.Ardakani@Sun.COM int i; 1398*11963SAfshin.Ardakani@Sun.COM 1399*11963SAfshin.Ardakani@Sun.COM ASSERT(sib); 1400*11963SAfshin.Ardakani@Sun.COM ASSERT(sib->sib_maps); 1401*11963SAfshin.Ardakani@Sun.COM 1402*11963SAfshin.Ardakani@Sun.COM if (sib->sib_idmaph) 1403*11963SAfshin.Ardakani@Sun.COM kidmap_get_destroy(sib->sib_idmaph); 1404*11963SAfshin.Ardakani@Sun.COM 1405*11963SAfshin.Ardakani@Sun.COM if (sib->sib_flags & SMB_IDMAP_ID2SID) { 1406*11963SAfshin.Ardakani@Sun.COM /* 1407*11963SAfshin.Ardakani@Sun.COM * SIDs are allocated only when mapping 1408*11963SAfshin.Ardakani@Sun.COM * UID/GID to SIDs 1409*11963SAfshin.Ardakani@Sun.COM */ 1410*11963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) 1411*11963SAfshin.Ardakani@Sun.COM smb_sid_free(sib->sib_maps[i].sim_sid); 1412*11963SAfshin.Ardakani@Sun.COM } else if (sib->sib_flags & SMB_IDMAP_SID2ID) { 1413*11963SAfshin.Ardakani@Sun.COM /* 1414*11963SAfshin.Ardakani@Sun.COM * SID prefixes are allocated only when mapping 1415*11963SAfshin.Ardakani@Sun.COM * SIDs to UID/GID 1416*11963SAfshin.Ardakani@Sun.COM */ 1417*11963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) { 1418*11963SAfshin.Ardakani@Sun.COM domsid = sib->sib_maps[i].sim_domsid; 1419*11963SAfshin.Ardakani@Sun.COM if (domsid) 1420*11963SAfshin.Ardakani@Sun.COM smb_mem_free(domsid); 1421*11963SAfshin.Ardakani@Sun.COM } 1422*11963SAfshin.Ardakani@Sun.COM } 1423*11963SAfshin.Ardakani@Sun.COM 1424*11963SAfshin.Ardakani@Sun.COM if (sib->sib_size && sib->sib_maps) 1425*11963SAfshin.Ardakani@Sun.COM kmem_free(sib->sib_maps, sib->sib_size); 1426*11963SAfshin.Ardakani@Sun.COM } 1427*11963SAfshin.Ardakani@Sun.COM 1428*11963SAfshin.Ardakani@Sun.COM /* 1429*11963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getid 1430*11963SAfshin.Ardakani@Sun.COM * 1431*11963SAfshin.Ardakani@Sun.COM * Queue a request to map the given SID to a UID or GID. 1432*11963SAfshin.Ardakani@Sun.COM * 1433*11963SAfshin.Ardakani@Sun.COM * sim->sim_id should point to variable that's supposed to 1434*11963SAfshin.Ardakani@Sun.COM * hold the returned UID/GID. This needs to be setup by caller 1435*11963SAfshin.Ardakani@Sun.COM * of this function. 1436*11963SAfshin.Ardakani@Sun.COM * 1437*11963SAfshin.Ardakani@Sun.COM * If requested ID type is known, it's passed as 'idtype', 1438*11963SAfshin.Ardakani@Sun.COM * if it's unknown it'll be returned in sim->sim_idtype. 1439*11963SAfshin.Ardakani@Sun.COM */ 1440*11963SAfshin.Ardakani@Sun.COM idmap_stat 1441*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 1442*11963SAfshin.Ardakani@Sun.COM smb_sid_t *sid, int idtype) 1443*11963SAfshin.Ardakani@Sun.COM { 1444*11963SAfshin.Ardakani@Sun.COM char strsid[SMB_SID_STRSZ]; 1445*11963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat; 1446*11963SAfshin.Ardakani@Sun.COM 1447*11963SAfshin.Ardakani@Sun.COM ASSERT(idmaph); 1448*11963SAfshin.Ardakani@Sun.COM ASSERT(sim); 1449*11963SAfshin.Ardakani@Sun.COM ASSERT(sid); 1450*11963SAfshin.Ardakani@Sun.COM 1451*11963SAfshin.Ardakani@Sun.COM smb_sid_tostr(sid, strsid); 1452*11963SAfshin.Ardakani@Sun.COM if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0) 1453*11963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_SID); 1454*11963SAfshin.Ardakani@Sun.COM sim->sim_domsid = smb_mem_strdup(strsid); 1455*11963SAfshin.Ardakani@Sun.COM 1456*11963SAfshin.Ardakani@Sun.COM switch (idtype) { 1457*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 1458*11963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid, 1459*11963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_stat); 1460*11963SAfshin.Ardakani@Sun.COM break; 1461*11963SAfshin.Ardakani@Sun.COM 1462*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 1463*11963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid, 1464*11963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_stat); 1465*11963SAfshin.Ardakani@Sun.COM break; 1466*11963SAfshin.Ardakani@Sun.COM 1467*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_UNKNOWN: 1468*11963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid, 1469*11963SAfshin.Ardakani@Sun.COM sim->sim_rid, sim->sim_id, &sim->sim_idtype, 1470*11963SAfshin.Ardakani@Sun.COM &sim->sim_stat); 1471*11963SAfshin.Ardakani@Sun.COM break; 1472*11963SAfshin.Ardakani@Sun.COM 1473*11963SAfshin.Ardakani@Sun.COM default: 1474*11963SAfshin.Ardakani@Sun.COM ASSERT(0); 1475*11963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 1476*11963SAfshin.Ardakani@Sun.COM } 1477*11963SAfshin.Ardakani@Sun.COM 1478*11963SAfshin.Ardakani@Sun.COM return (idm_stat); 1479*11963SAfshin.Ardakani@Sun.COM } 1480*11963SAfshin.Ardakani@Sun.COM 1481*11963SAfshin.Ardakani@Sun.COM /* 1482*11963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getsid 1483*11963SAfshin.Ardakani@Sun.COM * 1484*11963SAfshin.Ardakani@Sun.COM * Queue a request to map the given UID/GID to a SID. 1485*11963SAfshin.Ardakani@Sun.COM * 1486*11963SAfshin.Ardakani@Sun.COM * sim->sim_domsid and sim->sim_rid will contain the mapping 1487*11963SAfshin.Ardakani@Sun.COM * result upon successful process of the batched request. 1488*11963SAfshin.Ardakani@Sun.COM */ 1489*11963SAfshin.Ardakani@Sun.COM idmap_stat 1490*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim, 1491*11963SAfshin.Ardakani@Sun.COM uid_t id, int idtype) 1492*11963SAfshin.Ardakani@Sun.COM { 1493*11963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat; 1494*11963SAfshin.Ardakani@Sun.COM 1495*11963SAfshin.Ardakani@Sun.COM switch (idtype) { 1496*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_USER: 1497*11963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getsidbyuid(idmaph, id, 1498*11963SAfshin.Ardakani@Sun.COM (const char **)&sim->sim_domsid, &sim->sim_rid, 1499*11963SAfshin.Ardakani@Sun.COM &sim->sim_stat); 1500*11963SAfshin.Ardakani@Sun.COM break; 1501*11963SAfshin.Ardakani@Sun.COM 1502*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUP: 1503*11963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_batch_getsidbygid(idmaph, id, 1504*11963SAfshin.Ardakani@Sun.COM (const char **)&sim->sim_domsid, &sim->sim_rid, 1505*11963SAfshin.Ardakani@Sun.COM &sim->sim_stat); 1506*11963SAfshin.Ardakani@Sun.COM break; 1507*11963SAfshin.Ardakani@Sun.COM 1508*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_OWNERAT: 1509*11963SAfshin.Ardakani@Sun.COM /* Current Owner S-1-5-32-766 */ 1510*11963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR; 1511*11963SAfshin.Ardakani@Sun.COM sim->sim_rid = SECURITY_CURRENT_OWNER_RID; 1512*11963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS; 1513*11963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS; 1514*11963SAfshin.Ardakani@Sun.COM break; 1515*11963SAfshin.Ardakani@Sun.COM 1516*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_GROUPAT: 1517*11963SAfshin.Ardakani@Sun.COM /* Current Group S-1-5-32-767 */ 1518*11963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR; 1519*11963SAfshin.Ardakani@Sun.COM sim->sim_rid = SECURITY_CURRENT_GROUP_RID; 1520*11963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS; 1521*11963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS; 1522*11963SAfshin.Ardakani@Sun.COM break; 1523*11963SAfshin.Ardakani@Sun.COM 1524*11963SAfshin.Ardakani@Sun.COM case SMB_IDMAP_EVERYONE: 1525*11963SAfshin.Ardakani@Sun.COM /* Everyone S-1-1-0 */ 1526*11963SAfshin.Ardakani@Sun.COM sim->sim_domsid = NT_WORLD_AUTH_SIDSTR; 1527*11963SAfshin.Ardakani@Sun.COM sim->sim_rid = 0; 1528*11963SAfshin.Ardakani@Sun.COM sim->sim_stat = IDMAP_SUCCESS; 1529*11963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_SUCCESS; 1530*11963SAfshin.Ardakani@Sun.COM break; 1531*11963SAfshin.Ardakani@Sun.COM 1532*11963SAfshin.Ardakani@Sun.COM default: 1533*11963SAfshin.Ardakani@Sun.COM ASSERT(0); 1534*11963SAfshin.Ardakani@Sun.COM return (IDMAP_ERR_ARG); 1535*11963SAfshin.Ardakani@Sun.COM } 1536*11963SAfshin.Ardakani@Sun.COM 1537*11963SAfshin.Ardakani@Sun.COM return (idm_stat); 1538*11963SAfshin.Ardakani@Sun.COM } 1539*11963SAfshin.Ardakani@Sun.COM 1540*11963SAfshin.Ardakani@Sun.COM /* 1541*11963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_binsid 1542*11963SAfshin.Ardakani@Sun.COM * 1543*11963SAfshin.Ardakani@Sun.COM * Convert sidrids to binary sids 1544*11963SAfshin.Ardakani@Sun.COM * 1545*11963SAfshin.Ardakani@Sun.COM * Returns 0 if successful and non-zero upon failure. 1546*11963SAfshin.Ardakani@Sun.COM */ 1547*11963SAfshin.Ardakani@Sun.COM static int 1548*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_binsid(smb_idmap_batch_t *sib) 1549*11963SAfshin.Ardakani@Sun.COM { 1550*11963SAfshin.Ardakani@Sun.COM smb_sid_t *sid; 1551*11963SAfshin.Ardakani@Sun.COM smb_idmap_t *sim; 1552*11963SAfshin.Ardakani@Sun.COM int i; 1553*11963SAfshin.Ardakani@Sun.COM 1554*11963SAfshin.Ardakani@Sun.COM if (sib->sib_flags & SMB_IDMAP_SID2ID) 1555*11963SAfshin.Ardakani@Sun.COM /* This operation is not required */ 1556*11963SAfshin.Ardakani@Sun.COM return (0); 1557*11963SAfshin.Ardakani@Sun.COM 1558*11963SAfshin.Ardakani@Sun.COM sim = sib->sib_maps; 1559*11963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; sim++, i++) { 1560*11963SAfshin.Ardakani@Sun.COM ASSERT(sim->sim_domsid); 1561*11963SAfshin.Ardakani@Sun.COM if (sim->sim_domsid == NULL) 1562*11963SAfshin.Ardakani@Sun.COM return (1); 1563*11963SAfshin.Ardakani@Sun.COM 1564*11963SAfshin.Ardakani@Sun.COM if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL) 1565*11963SAfshin.Ardakani@Sun.COM return (1); 1566*11963SAfshin.Ardakani@Sun.COM 1567*11963SAfshin.Ardakani@Sun.COM sim->sim_sid = smb_sid_splice(sid, sim->sim_rid); 1568*11963SAfshin.Ardakani@Sun.COM smb_sid_free(sid); 1569*11963SAfshin.Ardakani@Sun.COM } 1570*11963SAfshin.Ardakani@Sun.COM 1571*11963SAfshin.Ardakani@Sun.COM return (0); 1572*11963SAfshin.Ardakani@Sun.COM } 1573*11963SAfshin.Ardakani@Sun.COM 1574*11963SAfshin.Ardakani@Sun.COM /* 1575*11963SAfshin.Ardakani@Sun.COM * smb_idmap_batch_getmappings 1576*11963SAfshin.Ardakani@Sun.COM * 1577*11963SAfshin.Ardakani@Sun.COM * trigger ID mapping service to get the mappings for queued 1578*11963SAfshin.Ardakani@Sun.COM * requests. 1579*11963SAfshin.Ardakani@Sun.COM * 1580*11963SAfshin.Ardakani@Sun.COM * Checks the result of all the queued requests. 1581*11963SAfshin.Ardakani@Sun.COM * If this is a Solaris -> Windows mapping it generates 1582*11963SAfshin.Ardakani@Sun.COM * binary SIDs from returned (domsid, rid) pairs. 1583*11963SAfshin.Ardakani@Sun.COM */ 1584*11963SAfshin.Ardakani@Sun.COM idmap_stat 1585*11963SAfshin.Ardakani@Sun.COM smb_idmap_batch_getmappings(smb_idmap_batch_t *sib) 1586*11963SAfshin.Ardakani@Sun.COM { 1587*11963SAfshin.Ardakani@Sun.COM idmap_stat idm_stat = IDMAP_SUCCESS; 1588*11963SAfshin.Ardakani@Sun.COM int i; 1589*11963SAfshin.Ardakani@Sun.COM 1590*11963SAfshin.Ardakani@Sun.COM idm_stat = kidmap_get_mappings(sib->sib_idmaph); 1591*11963SAfshin.Ardakani@Sun.COM if (idm_stat != IDMAP_SUCCESS) 1592*11963SAfshin.Ardakani@Sun.COM return (idm_stat); 1593*11963SAfshin.Ardakani@Sun.COM 1594*11963SAfshin.Ardakani@Sun.COM /* 1595*11963SAfshin.Ardakani@Sun.COM * Check the status for all the queued requests 1596*11963SAfshin.Ardakani@Sun.COM */ 1597*11963SAfshin.Ardakani@Sun.COM for (i = 0; i < sib->sib_nmap; i++) { 1598*11963SAfshin.Ardakani@Sun.COM if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS) 1599*11963SAfshin.Ardakani@Sun.COM return (sib->sib_maps[i].sim_stat); 1600*11963SAfshin.Ardakani@Sun.COM } 1601*11963SAfshin.Ardakani@Sun.COM 1602*11963SAfshin.Ardakani@Sun.COM if (smb_idmap_batch_binsid(sib) != 0) 1603*11963SAfshin.Ardakani@Sun.COM idm_stat = IDMAP_ERR_OTHER; 1604*11963SAfshin.Ardakani@Sun.COM 1605*11963SAfshin.Ardakani@Sun.COM return (idm_stat); 1606*11963SAfshin.Ardakani@Sun.COM } 1607*11963SAfshin.Ardakani@Sun.COM 1608*11963SAfshin.Ardakani@Sun.COM uint64_t 1609*11963SAfshin.Ardakani@Sun.COM smb_time_unix_to_nt(timestruc_t *unix_time) 1610*11963SAfshin.Ardakani@Sun.COM { 1611*11963SAfshin.Ardakani@Sun.COM uint64_t nt_time; 1612*11963SAfshin.Ardakani@Sun.COM 1613*11963SAfshin.Ardakani@Sun.COM if ((unix_time->tv_sec == 0) && (unix_time->tv_nsec == 0)) 1614*11963SAfshin.Ardakani@Sun.COM return (0); 1615*11963SAfshin.Ardakani@Sun.COM 1616*11963SAfshin.Ardakani@Sun.COM nt_time = unix_time->tv_sec; 1617*11963SAfshin.Ardakani@Sun.COM nt_time *= 10000000; /* seconds to 100ns */ 1618*11963SAfshin.Ardakani@Sun.COM nt_time += unix_time->tv_nsec / 100; 1619*11963SAfshin.Ardakani@Sun.COM return (nt_time + NT_TIME_BIAS); 1620*11963SAfshin.Ardakani@Sun.COM } 1621*11963SAfshin.Ardakani@Sun.COM 1622*11963SAfshin.Ardakani@Sun.COM void 1623*11963SAfshin.Ardakani@Sun.COM smb_time_nt_to_unix(uint64_t nt_time, timestruc_t *unix_time) 1624*11963SAfshin.Ardakani@Sun.COM { 1625*11963SAfshin.Ardakani@Sun.COM uint32_t seconds; 1626*11963SAfshin.Ardakani@Sun.COM 1627*11963SAfshin.Ardakani@Sun.COM ASSERT(unix_time); 1628*11963SAfshin.Ardakani@Sun.COM 1629*11963SAfshin.Ardakani@Sun.COM if ((nt_time == 0) || (nt_time == -1)) { 1630*11963SAfshin.Ardakani@Sun.COM unix_time->tv_sec = 0; 1631*11963SAfshin.Ardakani@Sun.COM unix_time->tv_nsec = 0; 1632*11963SAfshin.Ardakani@Sun.COM return; 1633*11963SAfshin.Ardakani@Sun.COM } 1634*11963SAfshin.Ardakani@Sun.COM 1635*11963SAfshin.Ardakani@Sun.COM nt_time -= NT_TIME_BIAS; 1636*11963SAfshin.Ardakani@Sun.COM seconds = nt_time / 10000000; 1637*11963SAfshin.Ardakani@Sun.COM unix_time->tv_sec = seconds; 1638*11963SAfshin.Ardakani@Sun.COM unix_time->tv_nsec = (nt_time % 10000000) * 100; 1639*11963SAfshin.Ardakani@Sun.COM } 1640*11963SAfshin.Ardakani@Sun.COM 1641*11963SAfshin.Ardakani@Sun.COM /* 1642*11963SAfshin.Ardakani@Sun.COM * smb_time_gmt_to_local, smb_time_local_to_gmt 1643*11963SAfshin.Ardakani@Sun.COM * 1644*11963SAfshin.Ardakani@Sun.COM * Apply the gmt offset to convert between local time and gmt 1645*11963SAfshin.Ardakani@Sun.COM */ 1646*11963SAfshin.Ardakani@Sun.COM int32_t 1647*11963SAfshin.Ardakani@Sun.COM smb_time_gmt_to_local(smb_request_t *sr, int32_t gmt) 1648*11963SAfshin.Ardakani@Sun.COM { 1649*11963SAfshin.Ardakani@Sun.COM if ((gmt == 0) || (gmt == -1)) 1650*11963SAfshin.Ardakani@Sun.COM return (0); 1651*11963SAfshin.Ardakani@Sun.COM 1652*11963SAfshin.Ardakani@Sun.COM return (gmt - sr->sr_gmtoff); 1653*11963SAfshin.Ardakani@Sun.COM } 1654*11963SAfshin.Ardakani@Sun.COM 1655*11963SAfshin.Ardakani@Sun.COM int32_t 1656*11963SAfshin.Ardakani@Sun.COM smb_time_local_to_gmt(smb_request_t *sr, int32_t local) 1657*11963SAfshin.Ardakani@Sun.COM { 1658*11963SAfshin.Ardakani@Sun.COM if ((local == 0) || (local == -1)) 1659*11963SAfshin.Ardakani@Sun.COM return (0); 1660*11963SAfshin.Ardakani@Sun.COM 1661*11963SAfshin.Ardakani@Sun.COM return (local + sr->sr_gmtoff); 1662*11963SAfshin.Ardakani@Sun.COM } 1663*11963SAfshin.Ardakani@Sun.COM 1664*11963SAfshin.Ardakani@Sun.COM 1665*11963SAfshin.Ardakani@Sun.COM /* 1666*11963SAfshin.Ardakani@Sun.COM * smb_time_dos_to_unix 1667*11963SAfshin.Ardakani@Sun.COM * 1668*11963SAfshin.Ardakani@Sun.COM * Convert SMB_DATE & SMB_TIME values to a unix timestamp. 1669*11963SAfshin.Ardakani@Sun.COM * 1670*11963SAfshin.Ardakani@Sun.COM * A date/time field of 0 means that that server file system 1671*11963SAfshin.Ardakani@Sun.COM * assigned value need not be changed. The behaviour when the 1672*11963SAfshin.Ardakani@Sun.COM * date/time field is set to -1 is not documented but is 1673*11963SAfshin.Ardakani@Sun.COM * generally treated like 0. 1674*11963SAfshin.Ardakani@Sun.COM * If date or time is 0 or -1 the unix time is returned as 0 1675*11963SAfshin.Ardakani@Sun.COM * so that the caller can identify and handle this special case. 1676*11963SAfshin.Ardakani@Sun.COM */ 1677*11963SAfshin.Ardakani@Sun.COM int32_t 1678*11963SAfshin.Ardakani@Sun.COM smb_time_dos_to_unix(int16_t date, int16_t time) 1679*11963SAfshin.Ardakani@Sun.COM { 1680*11963SAfshin.Ardakani@Sun.COM struct tm atm; 1681*11963SAfshin.Ardakani@Sun.COM 1682*11963SAfshin.Ardakani@Sun.COM if (((date == 0) || (time == 0)) || 1683*11963SAfshin.Ardakani@Sun.COM ((date == -1) || (time == -1))) { 1684*11963SAfshin.Ardakani@Sun.COM return (0); 1685*11963SAfshin.Ardakani@Sun.COM } 1686*11963SAfshin.Ardakani@Sun.COM 1687*11963SAfshin.Ardakani@Sun.COM atm.tm_year = ((date >> 9) & 0x3F) + 80; 1688*11963SAfshin.Ardakani@Sun.COM atm.tm_mon = ((date >> 5) & 0x0F) - 1; 1689*11963SAfshin.Ardakani@Sun.COM atm.tm_mday = ((date >> 0) & 0x1F); 1690*11963SAfshin.Ardakani@Sun.COM atm.tm_hour = ((time >> 11) & 0x1F); 1691*11963SAfshin.Ardakani@Sun.COM atm.tm_min = ((time >> 5) & 0x3F); 1692*11963SAfshin.Ardakani@Sun.COM atm.tm_sec = ((time >> 0) & 0x1F) << 1; 1693*11963SAfshin.Ardakani@Sun.COM 1694*11963SAfshin.Ardakani@Sun.COM return (smb_timegm(&atm)); 1695*11963SAfshin.Ardakani@Sun.COM } 1696*11963SAfshin.Ardakani@Sun.COM 1697*11963SAfshin.Ardakani@Sun.COM void 1698*11963SAfshin.Ardakani@Sun.COM smb_time_unix_to_dos(int32_t ux_time, int16_t *date_p, int16_t *time_p) 1699*11963SAfshin.Ardakani@Sun.COM { 1700*11963SAfshin.Ardakani@Sun.COM struct tm atm; 1701*11963SAfshin.Ardakani@Sun.COM int i; 1702*11963SAfshin.Ardakani@Sun.COM time_t tmp_time; 1703*11963SAfshin.Ardakani@Sun.COM 1704*11963SAfshin.Ardakani@Sun.COM if (ux_time == 0) { 1705*11963SAfshin.Ardakani@Sun.COM *date_p = 0; 1706*11963SAfshin.Ardakani@Sun.COM *time_p = 0; 1707*11963SAfshin.Ardakani@Sun.COM return; 1708*11963SAfshin.Ardakani@Sun.COM } 1709*11963SAfshin.Ardakani@Sun.COM 1710*11963SAfshin.Ardakani@Sun.COM tmp_time = (time_t)ux_time; 1711*11963SAfshin.Ardakani@Sun.COM (void) smb_gmtime_r(&tmp_time, &atm); 1712*11963SAfshin.Ardakani@Sun.COM 1713*11963SAfshin.Ardakani@Sun.COM if (date_p) { 1714*11963SAfshin.Ardakani@Sun.COM i = 0; 1715*11963SAfshin.Ardakani@Sun.COM i += atm.tm_year - 80; 1716*11963SAfshin.Ardakani@Sun.COM i <<= 4; 1717*11963SAfshin.Ardakani@Sun.COM i += atm.tm_mon + 1; 1718*11963SAfshin.Ardakani@Sun.COM i <<= 5; 1719*11963SAfshin.Ardakani@Sun.COM i += atm.tm_mday; 1720*11963SAfshin.Ardakani@Sun.COM 1721*11963SAfshin.Ardakani@Sun.COM *date_p = (short)i; 1722*11963SAfshin.Ardakani@Sun.COM } 1723*11963SAfshin.Ardakani@Sun.COM if (time_p) { 1724*11963SAfshin.Ardakani@Sun.COM i = 0; 1725*11963SAfshin.Ardakani@Sun.COM i += atm.tm_hour; 1726*11963SAfshin.Ardakani@Sun.COM i <<= 6; 1727*11963SAfshin.Ardakani@Sun.COM i += atm.tm_min; 1728*11963SAfshin.Ardakani@Sun.COM i <<= 5; 1729*11963SAfshin.Ardakani@Sun.COM i += atm.tm_sec >> 1; 1730*11963SAfshin.Ardakani@Sun.COM 1731*11963SAfshin.Ardakani@Sun.COM *time_p = (short)i; 1732*11963SAfshin.Ardakani@Sun.COM } 1733*11963SAfshin.Ardakani@Sun.COM } 1734*11963SAfshin.Ardakani@Sun.COM 1735*11963SAfshin.Ardakani@Sun.COM 1736*11963SAfshin.Ardakani@Sun.COM /* 1737*11963SAfshin.Ardakani@Sun.COM * smb_gmtime_r 1738*11963SAfshin.Ardakani@Sun.COM * 1739*11963SAfshin.Ardakani@Sun.COM * Thread-safe version of smb_gmtime. Returns a null pointer if either 1740*11963SAfshin.Ardakani@Sun.COM * input parameter is a null pointer. Otherwise returns a pointer 1741*11963SAfshin.Ardakani@Sun.COM * to result. 1742*11963SAfshin.Ardakani@Sun.COM * 1743*11963SAfshin.Ardakani@Sun.COM * Day of the week calculation: the Epoch was a thursday. 1744*11963SAfshin.Ardakani@Sun.COM * 1745*11963SAfshin.Ardakani@Sun.COM * There are no timezone corrections so tm_isdst and tm_gmtoff are 1746*11963SAfshin.Ardakani@Sun.COM * always zero, and the zone is always WET. 1747*11963SAfshin.Ardakani@Sun.COM */ 1748*11963SAfshin.Ardakani@Sun.COM struct tm * 1749*11963SAfshin.Ardakani@Sun.COM smb_gmtime_r(time_t *clock, struct tm *result) 1750*11963SAfshin.Ardakani@Sun.COM { 1751*11963SAfshin.Ardakani@Sun.COM time_t tsec; 1752*11963SAfshin.Ardakani@Sun.COM int year; 1753*11963SAfshin.Ardakani@Sun.COM int month; 1754*11963SAfshin.Ardakani@Sun.COM int sec_per_month; 1755*11963SAfshin.Ardakani@Sun.COM 1756*11963SAfshin.Ardakani@Sun.COM if (clock == 0 || result == 0) 1757*11963SAfshin.Ardakani@Sun.COM return (0); 1758*11963SAfshin.Ardakani@Sun.COM 1759*11963SAfshin.Ardakani@Sun.COM bzero(result, sizeof (struct tm)); 1760*11963SAfshin.Ardakani@Sun.COM tsec = *clock; 1761*11963SAfshin.Ardakani@Sun.COM tsec -= tzh_leapcnt; 1762*11963SAfshin.Ardakani@Sun.COM 1763*11963SAfshin.Ardakani@Sun.COM result->tm_wday = tsec / SECSPERDAY; 1764*11963SAfshin.Ardakani@Sun.COM result->tm_wday = (result->tm_wday + TM_THURSDAY) % DAYSPERWEEK; 1765*11963SAfshin.Ardakani@Sun.COM 1766*11963SAfshin.Ardakani@Sun.COM year = EPOCH_YEAR; 1767*11963SAfshin.Ardakani@Sun.COM while (tsec >= (isleap(year) ? (SECSPERDAY * DAYSPERLYEAR) : 1768*11963SAfshin.Ardakani@Sun.COM (SECSPERDAY * DAYSPERNYEAR))) { 1769*11963SAfshin.Ardakani@Sun.COM if (isleap(year)) 1770*11963SAfshin.Ardakani@Sun.COM tsec -= SECSPERDAY * DAYSPERLYEAR; 1771*11963SAfshin.Ardakani@Sun.COM else 1772*11963SAfshin.Ardakani@Sun.COM tsec -= SECSPERDAY * DAYSPERNYEAR; 1773*11963SAfshin.Ardakani@Sun.COM 1774*11963SAfshin.Ardakani@Sun.COM ++year; 1775*11963SAfshin.Ardakani@Sun.COM } 1776*11963SAfshin.Ardakani@Sun.COM 1777*11963SAfshin.Ardakani@Sun.COM result->tm_year = year - TM_YEAR_BASE; 1778*11963SAfshin.Ardakani@Sun.COM result->tm_yday = tsec / SECSPERDAY; 1779*11963SAfshin.Ardakani@Sun.COM 1780*11963SAfshin.Ardakani@Sun.COM for (month = TM_JANUARY; month <= TM_DECEMBER; ++month) { 1781*11963SAfshin.Ardakani@Sun.COM sec_per_month = days_in_month[month] * SECSPERDAY; 1782*11963SAfshin.Ardakani@Sun.COM 1783*11963SAfshin.Ardakani@Sun.COM if (month == TM_FEBRUARY && isleap(year)) 1784*11963SAfshin.Ardakani@Sun.COM sec_per_month += SECSPERDAY; 1785*11963SAfshin.Ardakani@Sun.COM 1786*11963SAfshin.Ardakani@Sun.COM if (tsec < sec_per_month) 1787*11963SAfshin.Ardakani@Sun.COM break; 1788*11963SAfshin.Ardakani@Sun.COM 1789*11963SAfshin.Ardakani@Sun.COM tsec -= sec_per_month; 1790*11963SAfshin.Ardakani@Sun.COM } 1791*11963SAfshin.Ardakani@Sun.COM 1792*11963SAfshin.Ardakani@Sun.COM result->tm_mon = month; 1793*11963SAfshin.Ardakani@Sun.COM result->tm_mday = (tsec / SECSPERDAY) + 1; 1794*11963SAfshin.Ardakani@Sun.COM tsec %= SECSPERDAY; 1795*11963SAfshin.Ardakani@Sun.COM result->tm_sec = tsec % 60; 1796*11963SAfshin.Ardakani@Sun.COM tsec /= 60; 1797*11963SAfshin.Ardakani@Sun.COM result->tm_min = tsec % 60; 1798*11963SAfshin.Ardakani@Sun.COM tsec /= 60; 1799*11963SAfshin.Ardakani@Sun.COM result->tm_hour = (int)tsec; 1800*11963SAfshin.Ardakani@Sun.COM 1801*11963SAfshin.Ardakani@Sun.COM return (result); 1802*11963SAfshin.Ardakani@Sun.COM } 1803*11963SAfshin.Ardakani@Sun.COM 1804*11963SAfshin.Ardakani@Sun.COM 1805*11963SAfshin.Ardakani@Sun.COM /* 1806*11963SAfshin.Ardakani@Sun.COM * smb_timegm 1807*11963SAfshin.Ardakani@Sun.COM * 1808*11963SAfshin.Ardakani@Sun.COM * Converts the broken-down time in tm to a time value, i.e. the number 1809*11963SAfshin.Ardakani@Sun.COM * of seconds since the Epoch (00:00:00 UTC, January 1, 1970). This is 1810*11963SAfshin.Ardakani@Sun.COM * not a POSIX or ANSI function. Per the man page, the input values of 1811*11963SAfshin.Ardakani@Sun.COM * tm_wday and tm_yday are ignored and, as the input data is assumed to 1812*11963SAfshin.Ardakani@Sun.COM * represent GMT, we force tm_isdst and tm_gmtoff to 0. 1813*11963SAfshin.Ardakani@Sun.COM * 1814*11963SAfshin.Ardakani@Sun.COM * Before returning the clock time, we use smb_gmtime_r to set up tm_wday 1815*11963SAfshin.Ardakani@Sun.COM * and tm_yday, and bring the other fields within normal range. I don't 1816*11963SAfshin.Ardakani@Sun.COM * think this is really how it should be done but it's convenient for 1817*11963SAfshin.Ardakani@Sun.COM * now. 1818*11963SAfshin.Ardakani@Sun.COM */ 1819*11963SAfshin.Ardakani@Sun.COM time_t 1820*11963SAfshin.Ardakani@Sun.COM smb_timegm(struct tm *tm) 1821*11963SAfshin.Ardakani@Sun.COM { 1822*11963SAfshin.Ardakani@Sun.COM time_t tsec; 1823*11963SAfshin.Ardakani@Sun.COM int dd; 1824*11963SAfshin.Ardakani@Sun.COM int mm; 1825*11963SAfshin.Ardakani@Sun.COM int yy; 1826*11963SAfshin.Ardakani@Sun.COM int year; 1827*11963SAfshin.Ardakani@Sun.COM 1828*11963SAfshin.Ardakani@Sun.COM if (tm == 0) 1829*11963SAfshin.Ardakani@Sun.COM return (-1); 1830*11963SAfshin.Ardakani@Sun.COM 1831*11963SAfshin.Ardakani@Sun.COM year = tm->tm_year + TM_YEAR_BASE; 1832*11963SAfshin.Ardakani@Sun.COM tsec = tzh_leapcnt; 1833*11963SAfshin.Ardakani@Sun.COM 1834*11963SAfshin.Ardakani@Sun.COM for (yy = EPOCH_YEAR; yy < year; ++yy) { 1835*11963SAfshin.Ardakani@Sun.COM if (isleap(yy)) 1836*11963SAfshin.Ardakani@Sun.COM tsec += SECSPERDAY * DAYSPERLYEAR; 1837*11963SAfshin.Ardakani@Sun.COM else 1838*11963SAfshin.Ardakani@Sun.COM tsec += SECSPERDAY * DAYSPERNYEAR; 1839*11963SAfshin.Ardakani@Sun.COM } 1840*11963SAfshin.Ardakani@Sun.COM 1841*11963SAfshin.Ardakani@Sun.COM for (mm = TM_JANUARY; mm < tm->tm_mon; ++mm) { 1842*11963SAfshin.Ardakani@Sun.COM dd = days_in_month[mm] * SECSPERDAY; 1843*11963SAfshin.Ardakani@Sun.COM 1844*11963SAfshin.Ardakani@Sun.COM if (mm == TM_FEBRUARY && isleap(year)) 1845*11963SAfshin.Ardakani@Sun.COM dd += SECSPERDAY; 1846*11963SAfshin.Ardakani@Sun.COM 1847*11963SAfshin.Ardakani@Sun.COM tsec += dd; 1848*11963SAfshin.Ardakani@Sun.COM } 1849*11963SAfshin.Ardakani@Sun.COM 1850*11963SAfshin.Ardakani@Sun.COM tsec += (tm->tm_mday - 1) * SECSPERDAY; 1851*11963SAfshin.Ardakani@Sun.COM tsec += tm->tm_sec; 1852*11963SAfshin.Ardakani@Sun.COM tsec += tm->tm_min * SECSPERMIN; 1853*11963SAfshin.Ardakani@Sun.COM tsec += tm->tm_hour * SECSPERHOUR; 1854*11963SAfshin.Ardakani@Sun.COM 1855*11963SAfshin.Ardakani@Sun.COM tm->tm_isdst = 0; 1856*11963SAfshin.Ardakani@Sun.COM (void) smb_gmtime_r(&tsec, tm); 1857*11963SAfshin.Ardakani@Sun.COM return (tsec); 1858*11963SAfshin.Ardakani@Sun.COM } 1859*11963SAfshin.Ardakani@Sun.COM 1860*11963SAfshin.Ardakani@Sun.COM /* 1861*11963SAfshin.Ardakani@Sun.COM * smb_cred_set_sid 1862*11963SAfshin.Ardakani@Sun.COM * 1863*11963SAfshin.Ardakani@Sun.COM * Initialize the ksid based on the given smb_id_t. 1864*11963SAfshin.Ardakani@Sun.COM */ 1865*11963SAfshin.Ardakani@Sun.COM static void 1866*11963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(smb_id_t *id, ksid_t *ksid) 1867*11963SAfshin.Ardakani@Sun.COM { 1868*11963SAfshin.Ardakani@Sun.COM char sidstr[SMB_SID_STRSZ]; 1869*11963SAfshin.Ardakani@Sun.COM int rc; 1870*11963SAfshin.Ardakani@Sun.COM 1871*11963SAfshin.Ardakani@Sun.COM ASSERT(id); 1872*11963SAfshin.Ardakani@Sun.COM ASSERT(id->i_sid); 1873*11963SAfshin.Ardakani@Sun.COM 1874*11963SAfshin.Ardakani@Sun.COM ksid->ks_id = id->i_id; 1875*11963SAfshin.Ardakani@Sun.COM smb_sid_tostr(id->i_sid, sidstr); 1876*11963SAfshin.Ardakani@Sun.COM rc = smb_sid_splitstr(sidstr, &ksid->ks_rid); 1877*11963SAfshin.Ardakani@Sun.COM ASSERT(rc == 0); 1878*11963SAfshin.Ardakani@Sun.COM 1879*11963SAfshin.Ardakani@Sun.COM ksid->ks_attr = id->i_attrs; 1880*11963SAfshin.Ardakani@Sun.COM ksid->ks_domain = ksid_lookupdomain(sidstr); 1881*11963SAfshin.Ardakani@Sun.COM } 1882*11963SAfshin.Ardakani@Sun.COM 1883*11963SAfshin.Ardakani@Sun.COM /* 1884*11963SAfshin.Ardakani@Sun.COM * smb_cred_set_sidlist 1885*11963SAfshin.Ardakani@Sun.COM * 1886*11963SAfshin.Ardakani@Sun.COM * Allocate and initialize the ksidlist based on the Windows group list of the 1887*11963SAfshin.Ardakani@Sun.COM * access token. 1888*11963SAfshin.Ardakani@Sun.COM */ 1889*11963SAfshin.Ardakani@Sun.COM static ksidlist_t * 1890*11963SAfshin.Ardakani@Sun.COM smb_cred_set_sidlist(smb_ids_t *token_grps) 1891*11963SAfshin.Ardakani@Sun.COM { 1892*11963SAfshin.Ardakani@Sun.COM int i; 1893*11963SAfshin.Ardakani@Sun.COM ksidlist_t *lp; 1894*11963SAfshin.Ardakani@Sun.COM 1895*11963SAfshin.Ardakani@Sun.COM lp = kmem_zalloc(KSIDLIST_MEM(token_grps->i_cnt), KM_SLEEP); 1896*11963SAfshin.Ardakani@Sun.COM lp->ksl_ref = 1; 1897*11963SAfshin.Ardakani@Sun.COM lp->ksl_nsid = token_grps->i_cnt; 1898*11963SAfshin.Ardakani@Sun.COM lp->ksl_neid = 0; 1899*11963SAfshin.Ardakani@Sun.COM 1900*11963SAfshin.Ardakani@Sun.COM for (i = 0; i < lp->ksl_nsid; i++) { 1901*11963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&token_grps->i_ids[i], &lp->ksl_sids[i]); 1902*11963SAfshin.Ardakani@Sun.COM if (lp->ksl_sids[i].ks_id > IDMAP_WK__MAX_GID) 1903*11963SAfshin.Ardakani@Sun.COM lp->ksl_neid++; 1904*11963SAfshin.Ardakani@Sun.COM } 1905*11963SAfshin.Ardakani@Sun.COM 1906*11963SAfshin.Ardakani@Sun.COM return (lp); 1907*11963SAfshin.Ardakani@Sun.COM } 1908*11963SAfshin.Ardakani@Sun.COM 1909*11963SAfshin.Ardakani@Sun.COM /* 1910*11963SAfshin.Ardakani@Sun.COM * A Solaris credential (cred_t structure) will be allocated and 1911*11963SAfshin.Ardakani@Sun.COM * initialized based on the given Windows style user access token. 1912*11963SAfshin.Ardakani@Sun.COM * 1913*11963SAfshin.Ardakani@Sun.COM * cred's gid is set to the primary group of the mapped Solaris user. 1914*11963SAfshin.Ardakani@Sun.COM * When there is no such mapped user (i.e. the mapped UID is ephemeral) 1915*11963SAfshin.Ardakani@Sun.COM * or his/her primary group could not be obtained, cred's gid is set to 1916*11963SAfshin.Ardakani@Sun.COM * the mapped Solaris group of token's primary group. 1917*11963SAfshin.Ardakani@Sun.COM */ 1918*11963SAfshin.Ardakani@Sun.COM cred_t * 1919*11963SAfshin.Ardakani@Sun.COM smb_cred_create(smb_token_t *token, uint32_t *privileges) 1920*11963SAfshin.Ardakani@Sun.COM { 1921*11963SAfshin.Ardakani@Sun.COM ksid_t ksid; 1922*11963SAfshin.Ardakani@Sun.COM ksidlist_t *ksidlist = NULL; 1923*11963SAfshin.Ardakani@Sun.COM smb_posix_grps_t *posix_grps; 1924*11963SAfshin.Ardakani@Sun.COM cred_t *cr; 1925*11963SAfshin.Ardakani@Sun.COM gid_t gid; 1926*11963SAfshin.Ardakani@Sun.COM 1927*11963SAfshin.Ardakani@Sun.COM ASSERT(token); 1928*11963SAfshin.Ardakani@Sun.COM ASSERT(token->tkn_posix_grps); 1929*11963SAfshin.Ardakani@Sun.COM posix_grps = token->tkn_posix_grps; 1930*11963SAfshin.Ardakani@Sun.COM 1931*11963SAfshin.Ardakani@Sun.COM ASSERT(privileges); 1932*11963SAfshin.Ardakani@Sun.COM 1933*11963SAfshin.Ardakani@Sun.COM cr = crget(); 1934*11963SAfshin.Ardakani@Sun.COM ASSERT(cr != NULL); 1935*11963SAfshin.Ardakani@Sun.COM 1936*11963SAfshin.Ardakani@Sun.COM if (!IDMAP_ID_IS_EPHEMERAL(token->tkn_user.i_id) && 1937*11963SAfshin.Ardakani@Sun.COM (posix_grps->pg_ngrps != 0)) { 1938*11963SAfshin.Ardakani@Sun.COM gid = posix_grps->pg_grps[0]; 1939*11963SAfshin.Ardakani@Sun.COM } else { 1940*11963SAfshin.Ardakani@Sun.COM gid = token->tkn_primary_grp.i_id; 1941*11963SAfshin.Ardakani@Sun.COM } 1942*11963SAfshin.Ardakani@Sun.COM 1943*11963SAfshin.Ardakani@Sun.COM if (crsetugid(cr, token->tkn_user.i_id, gid) != 0) { 1944*11963SAfshin.Ardakani@Sun.COM crfree(cr); 1945*11963SAfshin.Ardakani@Sun.COM return (NULL); 1946*11963SAfshin.Ardakani@Sun.COM } 1947*11963SAfshin.Ardakani@Sun.COM 1948*11963SAfshin.Ardakani@Sun.COM if (crsetgroups(cr, posix_grps->pg_ngrps, posix_grps->pg_grps) != 0) { 1949*11963SAfshin.Ardakani@Sun.COM crfree(cr); 1950*11963SAfshin.Ardakani@Sun.COM return (NULL); 1951*11963SAfshin.Ardakani@Sun.COM } 1952*11963SAfshin.Ardakani@Sun.COM 1953*11963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&token->tkn_user, &ksid); 1954*11963SAfshin.Ardakani@Sun.COM crsetsid(cr, &ksid, KSID_USER); 1955*11963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&token->tkn_primary_grp, &ksid); 1956*11963SAfshin.Ardakani@Sun.COM crsetsid(cr, &ksid, KSID_GROUP); 1957*11963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&token->tkn_owner, &ksid); 1958*11963SAfshin.Ardakani@Sun.COM crsetsid(cr, &ksid, KSID_OWNER); 1959*11963SAfshin.Ardakani@Sun.COM ksidlist = smb_cred_set_sidlist(&token->tkn_win_grps); 1960*11963SAfshin.Ardakani@Sun.COM crsetsidlist(cr, ksidlist); 1961*11963SAfshin.Ardakani@Sun.COM 1962*11963SAfshin.Ardakani@Sun.COM *privileges = 0; 1963*11963SAfshin.Ardakani@Sun.COM 1964*11963SAfshin.Ardakani@Sun.COM if (smb_token_query_privilege(token, SE_BACKUP_LUID)) 1965*11963SAfshin.Ardakani@Sun.COM *privileges |= SMB_USER_PRIV_BACKUP; 1966*11963SAfshin.Ardakani@Sun.COM 1967*11963SAfshin.Ardakani@Sun.COM if (smb_token_query_privilege(token, SE_RESTORE_LUID)) 1968*11963SAfshin.Ardakani@Sun.COM *privileges |= SMB_USER_PRIV_RESTORE; 1969*11963SAfshin.Ardakani@Sun.COM 1970*11963SAfshin.Ardakani@Sun.COM if (smb_token_query_privilege(token, SE_TAKE_OWNERSHIP_LUID)) { 1971*11963SAfshin.Ardakani@Sun.COM *privileges |= SMB_USER_PRIV_TAKE_OWNERSHIP; 1972*11963SAfshin.Ardakani@Sun.COM (void) crsetpriv(cr, PRIV_FILE_CHOWN, NULL); 1973*11963SAfshin.Ardakani@Sun.COM } 1974*11963SAfshin.Ardakani@Sun.COM 1975*11963SAfshin.Ardakani@Sun.COM if (smb_token_query_privilege(token, SE_SECURITY_LUID)) 1976*11963SAfshin.Ardakani@Sun.COM *privileges |= SMB_USER_PRIV_SECURITY; 1977*11963SAfshin.Ardakani@Sun.COM 1978*11963SAfshin.Ardakani@Sun.COM return (cr); 1979*11963SAfshin.Ardakani@Sun.COM } 1980*11963SAfshin.Ardakani@Sun.COM 1981*11963SAfshin.Ardakani@Sun.COM /* 1982*11963SAfshin.Ardakani@Sun.COM * smb_cred_rele 1983*11963SAfshin.Ardakani@Sun.COM * 1984*11963SAfshin.Ardakani@Sun.COM * The reference count of the user's credential will get decremented if it 1985*11963SAfshin.Ardakani@Sun.COM * is non-zero. Otherwise, the credential will be freed. 1986*11963SAfshin.Ardakani@Sun.COM */ 1987*11963SAfshin.Ardakani@Sun.COM void 1988*11963SAfshin.Ardakani@Sun.COM smb_cred_rele(cred_t *cr) 1989*11963SAfshin.Ardakani@Sun.COM { 1990*11963SAfshin.Ardakani@Sun.COM ASSERT(cr); 1991*11963SAfshin.Ardakani@Sun.COM crfree(cr); 1992*11963SAfshin.Ardakani@Sun.COM } 1993*11963SAfshin.Ardakani@Sun.COM 1994*11963SAfshin.Ardakani@Sun.COM /* 1995*11963SAfshin.Ardakani@Sun.COM * smb_cred_is_member 1996*11963SAfshin.Ardakani@Sun.COM * 1997*11963SAfshin.Ardakani@Sun.COM * Same as smb_token_is_member. The only difference is that 1998*11963SAfshin.Ardakani@Sun.COM * we compare the given SID against user SID and the ksidlist 1999*11963SAfshin.Ardakani@Sun.COM * of the user's cred. 2000*11963SAfshin.Ardakani@Sun.COM */ 2001*11963SAfshin.Ardakani@Sun.COM int 2002*11963SAfshin.Ardakani@Sun.COM smb_cred_is_member(cred_t *cr, smb_sid_t *sid) 2003*11963SAfshin.Ardakani@Sun.COM { 2004*11963SAfshin.Ardakani@Sun.COM ksidlist_t *ksidlist; 2005*11963SAfshin.Ardakani@Sun.COM ksid_t ksid1, *ksid2; 2006*11963SAfshin.Ardakani@Sun.COM smb_id_t id; 2007*11963SAfshin.Ardakani@Sun.COM int i, rc = 0; 2008*11963SAfshin.Ardakani@Sun.COM 2009*11963SAfshin.Ardakani@Sun.COM ASSERT(cr); 2010*11963SAfshin.Ardakani@Sun.COM 2011*11963SAfshin.Ardakani@Sun.COM bzero(&id, sizeof (smb_id_t)); 2012*11963SAfshin.Ardakani@Sun.COM id.i_sid = sid; 2013*11963SAfshin.Ardakani@Sun.COM smb_cred_set_sid(&id, &ksid1); 2014*11963SAfshin.Ardakani@Sun.COM 2015*11963SAfshin.Ardakani@Sun.COM ksidlist = crgetsidlist(cr); 2016*11963SAfshin.Ardakani@Sun.COM ASSERT(ksidlist); 2017*11963SAfshin.Ardakani@Sun.COM ASSERT(ksid1.ks_domain); 2018*11963SAfshin.Ardakani@Sun.COM ASSERT(ksid1.ks_domain->kd_name); 2019*11963SAfshin.Ardakani@Sun.COM 2020*11963SAfshin.Ardakani@Sun.COM i = 0; 2021*11963SAfshin.Ardakani@Sun.COM ksid2 = crgetsid(cr, KSID_USER); 2022*11963SAfshin.Ardakani@Sun.COM do { 2023*11963SAfshin.Ardakani@Sun.COM ASSERT(ksid2->ks_domain); 2024*11963SAfshin.Ardakani@Sun.COM ASSERT(ksid2->ks_domain->kd_name); 2025*11963SAfshin.Ardakani@Sun.COM 2026*11963SAfshin.Ardakani@Sun.COM if (strcmp(ksid1.ks_domain->kd_name, 2027*11963SAfshin.Ardakani@Sun.COM ksid2->ks_domain->kd_name) == 0 && 2028*11963SAfshin.Ardakani@Sun.COM ksid1.ks_rid == ksid2->ks_rid) { 2029*11963SAfshin.Ardakani@Sun.COM rc = 1; 2030*11963SAfshin.Ardakani@Sun.COM break; 2031*11963SAfshin.Ardakani@Sun.COM } 2032*11963SAfshin.Ardakani@Sun.COM 2033*11963SAfshin.Ardakani@Sun.COM ksid2 = &ksidlist->ksl_sids[i]; 2034*11963SAfshin.Ardakani@Sun.COM } while (i++ < ksidlist->ksl_nsid); 2035*11963SAfshin.Ardakani@Sun.COM 2036*11963SAfshin.Ardakani@Sun.COM ksid_rele(&ksid1); 2037*11963SAfshin.Ardakani@Sun.COM return (rc); 2038*11963SAfshin.Ardakani@Sun.COM } 2039*11963SAfshin.Ardakani@Sun.COM 2040*11963SAfshin.Ardakani@Sun.COM /* 2041*11963SAfshin.Ardakani@Sun.COM * smb_cred_create_privs 2042*11963SAfshin.Ardakani@Sun.COM * 2043*11963SAfshin.Ardakani@Sun.COM * Creates a duplicate credential that contains system privileges for 2044*11963SAfshin.Ardakani@Sun.COM * certain SMB privileges: Backup and Restore. 2045*11963SAfshin.Ardakani@Sun.COM * 2046*11963SAfshin.Ardakani@Sun.COM */ 2047*11963SAfshin.Ardakani@Sun.COM cred_t * 2048*11963SAfshin.Ardakani@Sun.COM smb_cred_create_privs(cred_t *user_cr, uint32_t privileges) 2049*11963SAfshin.Ardakani@Sun.COM { 2050*11963SAfshin.Ardakani@Sun.COM cred_t *cr = NULL; 2051*11963SAfshin.Ardakani@Sun.COM 2052*11963SAfshin.Ardakani@Sun.COM ASSERT(user_cr != NULL); 2053*11963SAfshin.Ardakani@Sun.COM 2054*11963SAfshin.Ardakani@Sun.COM if (privileges & (SMB_USER_PRIV_BACKUP | SMB_USER_PRIV_RESTORE)) 2055*11963SAfshin.Ardakani@Sun.COM cr = crdup(user_cr); 2056*11963SAfshin.Ardakani@Sun.COM 2057*11963SAfshin.Ardakani@Sun.COM if (cr == NULL) 2058*11963SAfshin.Ardakani@Sun.COM return (NULL); 2059*11963SAfshin.Ardakani@Sun.COM 2060*11963SAfshin.Ardakani@Sun.COM if (privileges & SMB_USER_PRIV_BACKUP) { 2061*11963SAfshin.Ardakani@Sun.COM (void) crsetpriv(cr, PRIV_FILE_DAC_READ, 2062*11963SAfshin.Ardakani@Sun.COM PRIV_FILE_DAC_SEARCH, PRIV_SYS_MOUNT, NULL); 2063*11963SAfshin.Ardakani@Sun.COM } 2064*11963SAfshin.Ardakani@Sun.COM 2065*11963SAfshin.Ardakani@Sun.COM if (privileges & SMB_USER_PRIV_RESTORE) { 2066*11963SAfshin.Ardakani@Sun.COM (void) crsetpriv(cr, PRIV_FILE_DAC_WRITE, 2067*11963SAfshin.Ardakani@Sun.COM PRIV_FILE_CHOWN, PRIV_FILE_CHOWN_SELF, 2068*11963SAfshin.Ardakani@Sun.COM PRIV_FILE_DAC_SEARCH, PRIV_FILE_LINK_ANY, 2069*11963SAfshin.Ardakani@Sun.COM PRIV_FILE_OWNER, PRIV_FILE_SETID, PRIV_SYS_LINKDIR, 2070*11963SAfshin.Ardakani@Sun.COM PRIV_SYS_MOUNT, NULL); 2071*11963SAfshin.Ardakani@Sun.COM } 2072*11963SAfshin.Ardakani@Sun.COM 2073*11963SAfshin.Ardakani@Sun.COM return (cr); 2074*11963SAfshin.Ardakani@Sun.COM } 2075*11963SAfshin.Ardakani@Sun.COM 2076*11963SAfshin.Ardakani@Sun.COM /* 2077*11963SAfshin.Ardakani@Sun.COM * smb_pad_align 2078*11963SAfshin.Ardakani@Sun.COM * 2079*11963SAfshin.Ardakani@Sun.COM * Returns the number of bytes required to pad an offset to the 2080*11963SAfshin.Ardakani@Sun.COM * specified alignment. 2081*11963SAfshin.Ardakani@Sun.COM */ 2082*11963SAfshin.Ardakani@Sun.COM uint32_t 2083*11963SAfshin.Ardakani@Sun.COM smb_pad_align(uint32_t offset, uint32_t align) 2084*11963SAfshin.Ardakani@Sun.COM { 2085*11963SAfshin.Ardakani@Sun.COM uint32_t pad = offset % align; 2086*11963SAfshin.Ardakani@Sun.COM 2087*11963SAfshin.Ardakani@Sun.COM if (pad != 0) 2088*11963SAfshin.Ardakani@Sun.COM pad = align - pad; 2089*11963SAfshin.Ardakani@Sun.COM 2090*11963SAfshin.Ardakani@Sun.COM return (pad); 2091*11963SAfshin.Ardakani@Sun.COM } 2092*11963SAfshin.Ardakani@Sun.COM 2093*11963SAfshin.Ardakani@Sun.COM /* 2094*11963SAfshin.Ardakani@Sun.COM * smb_panic 2095*11963SAfshin.Ardakani@Sun.COM * 2096*11963SAfshin.Ardakani@Sun.COM * Logs the file name, function name and line number passed in and panics the 2097*11963SAfshin.Ardakani@Sun.COM * system. 2098*11963SAfshin.Ardakani@Sun.COM */ 2099*11963SAfshin.Ardakani@Sun.COM void 2100*11963SAfshin.Ardakani@Sun.COM smb_panic(char *file, const char *func, int line) 2101*11963SAfshin.Ardakani@Sun.COM { 2102*11963SAfshin.Ardakani@Sun.COM cmn_err(CE_PANIC, "%s:%s:%d\n", file, func, line); 2103*11963SAfshin.Ardakani@Sun.COM } 2104