12654012fSReza Sabdar /* 2b6b15642SReza Sabdar * Copyright 2009 Sun Microsystems, Inc. All rights reserved. 32654012fSReza Sabdar * Use is subject to license terms. 4*33f5ff17SMilan Jurik * Copyright 2012 Milan Jurik. All rights reserved. 52654012fSReza Sabdar */ 62654012fSReza Sabdar 72654012fSReza Sabdar /* 82654012fSReza Sabdar * BSD 3 Clause License 92654012fSReza Sabdar * 102654012fSReza Sabdar * Copyright (c) 2007, The Storage Networking Industry Association. 112654012fSReza Sabdar * 122654012fSReza Sabdar * Redistribution and use in source and binary forms, with or without 132654012fSReza Sabdar * modification, are permitted provided that the following conditions 142654012fSReza Sabdar * are met: 152654012fSReza Sabdar * - Redistributions of source code must retain the above copyright 162654012fSReza Sabdar * notice, this list of conditions and the following disclaimer. 172654012fSReza Sabdar * 182654012fSReza Sabdar * - Redistributions in binary form must reproduce the above copyright 192654012fSReza Sabdar * notice, this list of conditions and the following disclaimer in 202654012fSReza Sabdar * the documentation and/or other materials provided with the 212654012fSReza Sabdar * distribution. 222654012fSReza Sabdar * 232654012fSReza Sabdar * - Neither the name of The Storage Networking Industry Association (SNIA) 242654012fSReza Sabdar * nor the names of its contributors may be used to endorse or promote 252654012fSReza Sabdar * products derived from this software without specific prior written 262654012fSReza Sabdar * permission. 272654012fSReza Sabdar * 282654012fSReza Sabdar * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 292654012fSReza Sabdar * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 302654012fSReza Sabdar * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 312654012fSReza Sabdar * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 322654012fSReza Sabdar * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 332654012fSReza Sabdar * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 342654012fSReza Sabdar * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 352654012fSReza Sabdar * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 362654012fSReza Sabdar * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 372654012fSReza Sabdar * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 382654012fSReza Sabdar * POSSIBILITY OF SUCH DAMAGE. 392654012fSReza Sabdar */ 402654012fSReza Sabdar #include <stdio.h> 412654012fSReza Sabdar #include <stdlib.h> 422654012fSReza Sabdar #include <string.h> 432654012fSReza Sabdar #include <strings.h> 442654012fSReza Sabdar #include <cstack.h> 452654012fSReza Sabdar #include <ctype.h> 462654012fSReza Sabdar #include <tlm.h> 472654012fSReza Sabdar #include "tlm_proto.h" 482654012fSReza Sabdar 492654012fSReza Sabdar /* 502654012fSReza Sabdar * Implementation of a list based stack class. The stack only holds 512654012fSReza Sabdar * pointers/references to application objects. The objects are not 522654012fSReza Sabdar * copied and the stack never attempts to dereference or access the 532654012fSReza Sabdar * data objects. Applications should treat cstack_t references as 542654012fSReza Sabdar * opaque handles. 552654012fSReza Sabdar */ 562654012fSReza Sabdar 572654012fSReza Sabdar /* 582654012fSReza Sabdar * cstack_new 592654012fSReza Sabdar * 602654012fSReza Sabdar * Allocate and initialize a new stack, which is just an empty cstack_t. 612654012fSReza Sabdar * A pointer to the new stack is returned. This should be treated as an 622654012fSReza Sabdar * opaque handle by the caller. 632654012fSReza Sabdar */ 642654012fSReza Sabdar cstack_t * 652654012fSReza Sabdar cstack_new(void) 662654012fSReza Sabdar { 672654012fSReza Sabdar cstack_t *stk; 682654012fSReza Sabdar 692654012fSReza Sabdar if ((stk = ndmp_malloc(sizeof (cstack_t))) == NULL) 702654012fSReza Sabdar return (NULL); 712654012fSReza Sabdar 722654012fSReza Sabdar return (stk); 732654012fSReza Sabdar } 742654012fSReza Sabdar 752654012fSReza Sabdar 762654012fSReza Sabdar /* 772654012fSReza Sabdar * cstack_delete 782654012fSReza Sabdar * 792654012fSReza Sabdar * Deallocate the stack. This goes through the list freeing all of the 802654012fSReza Sabdar * cstack nodes but not the data because we don't know how the data was 812654012fSReza Sabdar * allocated. A stack really should be empty before it is deleted. 822654012fSReza Sabdar */ 832654012fSReza Sabdar void 842654012fSReza Sabdar cstack_delete(cstack_t *stk) 852654012fSReza Sabdar { 862654012fSReza Sabdar cstack_t *tmp; 872654012fSReza Sabdar 882654012fSReza Sabdar if (stk == NULL) { 892654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_delete: invalid stack"); 902654012fSReza Sabdar return; 912654012fSReza Sabdar } 922654012fSReza Sabdar 932654012fSReza Sabdar while ((tmp = stk->next) != NULL) { 942654012fSReza Sabdar stk->next = tmp->next; 952654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_delete(element): 0x%p", tmp); 962654012fSReza Sabdar free(tmp); 972654012fSReza Sabdar } 982654012fSReza Sabdar 992654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_delete: 0x%p", stk); 1002654012fSReza Sabdar free(stk); 1012654012fSReza Sabdar } 1022654012fSReza Sabdar 1032654012fSReza Sabdar 1042654012fSReza Sabdar /* 1052654012fSReza Sabdar * cstack_push 1062654012fSReza Sabdar * 1072654012fSReza Sabdar * Push an element onto the stack. Allocate a new node and assign the 1082654012fSReza Sabdar * data and len values. We don't care what about the real values of 1092654012fSReza Sabdar * data or len and we never try to access them. The stack head will 1102654012fSReza Sabdar * point to the new node. 1112654012fSReza Sabdar * 1122654012fSReza Sabdar * Returns 0 on success. Otherwise returns -1 to indicate overflow. 1132654012fSReza Sabdar */ 1142654012fSReza Sabdar int 1152654012fSReza Sabdar cstack_push(cstack_t *stk, void *data, int len) 1162654012fSReza Sabdar { 1172654012fSReza Sabdar cstack_t *stk_node; 1182654012fSReza Sabdar 1192654012fSReza Sabdar if (stk == NULL) { 1202654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_push: invalid stack"); 1212654012fSReza Sabdar return (-1); 1222654012fSReza Sabdar } 1232654012fSReza Sabdar 1242654012fSReza Sabdar if ((stk_node = ndmp_malloc(sizeof (cstack_t))) == NULL) 1252654012fSReza Sabdar return (-1); 1262654012fSReza Sabdar 1272654012fSReza Sabdar stk_node->data = data; 1282654012fSReza Sabdar stk_node->len = len; 1292654012fSReza Sabdar stk_node->next = stk->next; 1302654012fSReza Sabdar stk->next = stk_node; 1312654012fSReza Sabdar 1322654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_push(0x%p): 0x%p", stk, stk_node); 1332654012fSReza Sabdar return (0); 1342654012fSReza Sabdar } 1352654012fSReza Sabdar 1362654012fSReza Sabdar 1372654012fSReza Sabdar /* 1382654012fSReza Sabdar * cstack_pop 1392654012fSReza Sabdar * 1402654012fSReza Sabdar * Pop an element off the stack. Set up the data and len references for 1412654012fSReza Sabdar * the caller, advance the stack head and free the popped stack node. 1422654012fSReza Sabdar * 1432654012fSReza Sabdar * Returns 0 on success. Otherwise returns -1 to indicate underflow. 1442654012fSReza Sabdar */ 1452654012fSReza Sabdar int 1462654012fSReza Sabdar cstack_pop(cstack_t *stk, void **data, int *len) 1472654012fSReza Sabdar { 1482654012fSReza Sabdar cstack_t *stk_node; 1492654012fSReza Sabdar 1502654012fSReza Sabdar if (stk == NULL) { 1512654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack"); 1522654012fSReza Sabdar return (-1); 1532654012fSReza Sabdar } 1542654012fSReza Sabdar 1552654012fSReza Sabdar if ((stk_node = stk->next) == NULL) { 1562654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow"); 1572654012fSReza Sabdar return (-1); 1582654012fSReza Sabdar } 1592654012fSReza Sabdar 1602654012fSReza Sabdar if (data) 1612654012fSReza Sabdar *data = stk_node->data; 1622654012fSReza Sabdar 1632654012fSReza Sabdar if (len) 1642654012fSReza Sabdar *len = stk_node->len; 1652654012fSReza Sabdar 1662654012fSReza Sabdar stk->next = stk_node->next; 1672654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_pop(0x%p): 0x%p", stk, stk_node); 1682654012fSReza Sabdar 1692654012fSReza Sabdar free(stk_node); 1702654012fSReza Sabdar return (0); 1712654012fSReza Sabdar } 1722654012fSReza Sabdar 1732654012fSReza Sabdar /* 1742654012fSReza Sabdar * cstack_top 1752654012fSReza Sabdar * 1762654012fSReza Sabdar * Returns the top data element on the stack without removing it. 1772654012fSReza Sabdar * 1782654012fSReza Sabdar * Returns 0 on success. Otherwise returns -1 to indicate underflow. 1792654012fSReza Sabdar */ 1802654012fSReza Sabdar int 1812654012fSReza Sabdar cstack_top(cstack_t *stk, void **data, int *len) 1822654012fSReza Sabdar { 1832654012fSReza Sabdar if (stk == NULL) { 1842654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack"); 1852654012fSReza Sabdar return (-1); 1862654012fSReza Sabdar } 1872654012fSReza Sabdar 1882654012fSReza Sabdar if (stk->next == NULL) { 1892654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow"); 1902654012fSReza Sabdar return (-1); 1912654012fSReza Sabdar } 1922654012fSReza Sabdar 1932654012fSReza Sabdar if (data) 1942654012fSReza Sabdar *data = stk->next->data; 1952654012fSReza Sabdar 1962654012fSReza Sabdar if (len) 1972654012fSReza Sabdar *len = stk->next->len; 1982654012fSReza Sabdar 1992654012fSReza Sabdar return (0); 2002654012fSReza Sabdar } 2012654012fSReza Sabdar 2022654012fSReza Sabdar /* 2032654012fSReza Sabdar * match 2042654012fSReza Sabdar * 2052654012fSReza Sabdar * Matching rules: 2062654012fSReza Sabdar * c Any non-special character matches itslef 2072654012fSReza Sabdar * ? Match any character 2082654012fSReza Sabdar * ab character 'a' followed by character 'b' 2092654012fSReza Sabdar * S Any string of non-special characters 2102654012fSReza Sabdar * AB String 'A' followed by string 'B' 2112654012fSReza Sabdar * * Any String, including the empty string 2122654012fSReza Sabdar */ 2132654012fSReza Sabdar boolean_t 2142654012fSReza Sabdar match(char *patn, char *str) 2152654012fSReza Sabdar { 2162654012fSReza Sabdar for (; ; ) { 2172654012fSReza Sabdar switch (*patn) { 2182654012fSReza Sabdar case 0: 2192654012fSReza Sabdar return (*str == 0); 2202654012fSReza Sabdar 2212654012fSReza Sabdar case '?': 2222654012fSReza Sabdar if (*str != 0) { 2232654012fSReza Sabdar str++; 2242654012fSReza Sabdar patn++; 2252654012fSReza Sabdar continue; 2262654012fSReza Sabdar } 227*33f5ff17SMilan Jurik return (FALSE); 2282654012fSReza Sabdar 2292654012fSReza Sabdar case '*': 2302654012fSReza Sabdar patn++; 2312654012fSReza Sabdar if (*patn == 0) 2322654012fSReza Sabdar return (TRUE); 2332654012fSReza Sabdar 2342654012fSReza Sabdar while (*str) { 2352654012fSReza Sabdar if (match(patn, str)) 2362654012fSReza Sabdar return (TRUE); 2372654012fSReza Sabdar str++; 2382654012fSReza Sabdar } 2392654012fSReza Sabdar return (FALSE); 2402654012fSReza Sabdar 2412654012fSReza Sabdar default: 2422654012fSReza Sabdar if (*str != *patn) 2432654012fSReza Sabdar return (FALSE); 2442654012fSReza Sabdar str++; 2452654012fSReza Sabdar patn++; 2462654012fSReza Sabdar continue; 2472654012fSReza Sabdar } 2482654012fSReza Sabdar } 2492654012fSReza Sabdar } 2502654012fSReza Sabdar 2512654012fSReza Sabdar /* 2522654012fSReza Sabdar * Match recursive call 2532654012fSReza Sabdar */ 2542654012fSReza Sabdar int 2552654012fSReza Sabdar match_ci(char *patn, char *str) 2562654012fSReza Sabdar { 2572654012fSReza Sabdar /* 2582654012fSReza Sabdar * "<" is a special pattern that matches only those names 2592654012fSReza Sabdar * that do NOT have an extension. "." and ".." are ok. 2602654012fSReza Sabdar */ 2612654012fSReza Sabdar if (strcmp(patn, "<") == 0) { 2622654012fSReza Sabdar if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0)) 2632654012fSReza Sabdar return (TRUE); 2642654012fSReza Sabdar if (strchr(str, '.') == 0) 2652654012fSReza Sabdar return (TRUE); 2662654012fSReza Sabdar return (FALSE); 2672654012fSReza Sabdar } 2682654012fSReza Sabdar for (; ; ) { 2692654012fSReza Sabdar switch (*patn) { 2702654012fSReza Sabdar case 0: 2712654012fSReza Sabdar return (*str == 0); 2722654012fSReza Sabdar 2732654012fSReza Sabdar case '?': 2742654012fSReza Sabdar if (*str != 0) { 2752654012fSReza Sabdar str++; 2762654012fSReza Sabdar patn++; 2772654012fSReza Sabdar continue; 2782654012fSReza Sabdar } 279*33f5ff17SMilan Jurik return (FALSE); 2802654012fSReza Sabdar 2812654012fSReza Sabdar case '*': 2822654012fSReza Sabdar patn++; 2832654012fSReza Sabdar if (*patn == 0) 2842654012fSReza Sabdar return (TRUE); 2852654012fSReza Sabdar 2862654012fSReza Sabdar while (*str) { 2872654012fSReza Sabdar if (match_ci(patn, str)) 2882654012fSReza Sabdar return (TRUE); 2892654012fSReza Sabdar str++; 2902654012fSReza Sabdar } 2912654012fSReza Sabdar return (FALSE); 2922654012fSReza Sabdar 2932654012fSReza Sabdar default: 2942654012fSReza Sabdar if (*str != *patn) { 2952654012fSReza Sabdar int c1 = *str; 2962654012fSReza Sabdar int c2 = *patn; 2972654012fSReza Sabdar 2982654012fSReza Sabdar c1 = tolower(c1); 2992654012fSReza Sabdar c2 = tolower(c2); 3002654012fSReza Sabdar if (c1 != c2) 3012654012fSReza Sabdar return (FALSE); 3022654012fSReza Sabdar } 3032654012fSReza Sabdar str++; 3042654012fSReza Sabdar patn++; 3052654012fSReza Sabdar continue; 3062654012fSReza Sabdar } 3072654012fSReza Sabdar } 3082654012fSReza Sabdar /* NOT REACHED */ 3092654012fSReza Sabdar } 3102654012fSReza Sabdar 3112654012fSReza Sabdar /* 3122654012fSReza Sabdar * Linear matching against a list utility function 3132654012fSReza Sabdar */ 3142654012fSReza Sabdar static boolean_t 3152654012fSReza Sabdar parse_match(char line, char *seps) 3162654012fSReza Sabdar { 3172654012fSReza Sabdar char *sep = seps; 3182654012fSReza Sabdar 3192654012fSReza Sabdar while (*sep != 0) { 3202654012fSReza Sabdar /* compare this char with the seperator list */ 3212654012fSReza Sabdar if (*sep == line) 3222654012fSReza Sabdar return (TRUE); 3232654012fSReza Sabdar sep++; 3242654012fSReza Sabdar } 3252654012fSReza Sabdar return (FALSE); 3262654012fSReza Sabdar } 3272654012fSReza Sabdar 3282654012fSReza Sabdar /* 3292654012fSReza Sabdar * Returns the next entry of the list after 3302654012fSReza Sabdar * each separator 3312654012fSReza Sabdar */ 3322654012fSReza Sabdar char * 3332654012fSReza Sabdar parse(char **line, char *seps) 3342654012fSReza Sabdar { 3352654012fSReza Sabdar char *start = *line; 3362654012fSReza Sabdar 3372654012fSReza Sabdar while (**line != 0) { 3382654012fSReza Sabdar *line = *line + 1; 3392654012fSReza Sabdar if (parse_match(**line, seps)) { 3402654012fSReza Sabdar /* hit a terminator, skip trailing terminators */ 3412654012fSReza Sabdar while (parse_match(**line, seps)) { 3422654012fSReza Sabdar **line = 0; 3432654012fSReza Sabdar *line = *line + 1; 3442654012fSReza Sabdar } 3452654012fSReza Sabdar break; 3462654012fSReza Sabdar } 3472654012fSReza Sabdar } 3482654012fSReza Sabdar return (start); 3492654012fSReza Sabdar } 3502654012fSReza Sabdar 3512654012fSReza Sabdar /* 3522654012fSReza Sabdar * oct_atoi 3532654012fSReza Sabdar * 3542654012fSReza Sabdar * Convert an octal string to integer 3552654012fSReza Sabdar */ 3562654012fSReza Sabdar int 3572654012fSReza Sabdar oct_atoi(char *p) 3582654012fSReza Sabdar { 3592654012fSReza Sabdar int v = 0; 3602654012fSReza Sabdar int c; 3612654012fSReza Sabdar 3622654012fSReza Sabdar while (*p == ' ') 3632654012fSReza Sabdar p++; 3642654012fSReza Sabdar 3652654012fSReza Sabdar while ('0' <= (c = *p++) && c <= '7') { 3662654012fSReza Sabdar v <<= 3; 3672654012fSReza Sabdar v += c - '0'; 3682654012fSReza Sabdar } 3692654012fSReza Sabdar 3702654012fSReza Sabdar return (v); 3712654012fSReza Sabdar } 3722654012fSReza Sabdar 3732654012fSReza Sabdar /* 3742654012fSReza Sabdar * strupr 3752654012fSReza Sabdar * 3762654012fSReza Sabdar * Convert a string to uppercase using the appropriate codepage. The 3772654012fSReza Sabdar * string is converted in place. A pointer to the string is returned. 3782654012fSReza Sabdar * There is an assumption here that uppercase and lowercase values 3792654012fSReza Sabdar * always result encode to the same length. 3802654012fSReza Sabdar */ 3812654012fSReza Sabdar char * 3822654012fSReza Sabdar strupr(char *s) 3832654012fSReza Sabdar { 3842654012fSReza Sabdar char c; 3852654012fSReza Sabdar unsigned char *p = (unsigned char *)s; 3862654012fSReza Sabdar 3872654012fSReza Sabdar while (*p) { 3882654012fSReza Sabdar c = toupper(*p); 3892654012fSReza Sabdar *p++ = c; 3902654012fSReza Sabdar } 3912654012fSReza Sabdar return (s); 3922654012fSReza Sabdar } 3932654012fSReza Sabdar 3942654012fSReza Sabdar /* 3952654012fSReza Sabdar * trim_whitespace 3962654012fSReza Sabdar * 3972654012fSReza Sabdar * Trim leading and trailing whitespace chars(as defined by isspace) 3982654012fSReza Sabdar * from a buffer. Example; if the input buffer contained " text ", 3992654012fSReza Sabdar * it will contain "text", when we return. We assume that the buffer 4002654012fSReza Sabdar * contains a null terminated string. A pointer to the buffer is 4012654012fSReza Sabdar * returned. 4022654012fSReza Sabdar */ 4032654012fSReza Sabdar char * 4042654012fSReza Sabdar trim_whitespace(char *buf) 4052654012fSReza Sabdar { 4062654012fSReza Sabdar char *p = buf; 4072654012fSReza Sabdar char *q = buf; 4082654012fSReza Sabdar 4092654012fSReza Sabdar if (buf == 0) 4102654012fSReza Sabdar return (0); 4112654012fSReza Sabdar 4122654012fSReza Sabdar while (*p && isspace(*p)) 4132654012fSReza Sabdar ++p; 4142654012fSReza Sabdar 4152654012fSReza Sabdar while ((*q = *p++) != 0) 4162654012fSReza Sabdar ++q; 4172654012fSReza Sabdar 4182654012fSReza Sabdar if (q != buf) { 4192654012fSReza Sabdar while ((--q, isspace(*q)) != 0) 4202654012fSReza Sabdar *q = '\0'; 4212654012fSReza Sabdar } 4222654012fSReza Sabdar 4232654012fSReza Sabdar return (buf); 4242654012fSReza Sabdar } 4252654012fSReza Sabdar 4262654012fSReza Sabdar /* 4272654012fSReza Sabdar * trim_name 4282654012fSReza Sabdar * 4292654012fSReza Sabdar * Trims the slash and dot slash from the beginning of the 4302654012fSReza Sabdar * path name. 4312654012fSReza Sabdar */ 4322654012fSReza Sabdar char * 4332654012fSReza Sabdar trim_name(char *nm) 4342654012fSReza Sabdar { 4352654012fSReza Sabdar while (*nm) { 4362654012fSReza Sabdar if (*nm == '/') { 4372654012fSReza Sabdar nm++; 4382654012fSReza Sabdar continue; 4392654012fSReza Sabdar } 4402654012fSReza Sabdar if (*nm == '.' && nm[1] == '/' && nm[2]) { 4412654012fSReza Sabdar nm += 2; 4422654012fSReza Sabdar continue; 4432654012fSReza Sabdar } 4442654012fSReza Sabdar break; 4452654012fSReza Sabdar } 4462654012fSReza Sabdar return (nm); 4472654012fSReza Sabdar } 4482654012fSReza Sabdar 4492654012fSReza Sabdar /* 4502654012fSReza Sabdar * get_volname 4512654012fSReza Sabdar * 4522654012fSReza Sabdar * Extract the volume name from the path 4532654012fSReza Sabdar */ 4542654012fSReza Sabdar char * 4552654012fSReza Sabdar get_volname(char *path) 4562654012fSReza Sabdar { 4572654012fSReza Sabdar char *cp, *save; 4582654012fSReza Sabdar int sp; 4592654012fSReza Sabdar 4602654012fSReza Sabdar if (!path) 4612654012fSReza Sabdar return (NULL); 4622654012fSReza Sabdar 4632654012fSReza Sabdar if (!(save = strdup(path))) 4642654012fSReza Sabdar return (NULL); 4652654012fSReza Sabdar 4662654012fSReza Sabdar sp = strspn(path, "/"); 4672654012fSReza Sabdar if (*(path + sp) == '\0') { 4682654012fSReza Sabdar free(save); 4692654012fSReza Sabdar return (NULL); 4702654012fSReza Sabdar } 4712654012fSReza Sabdar 4722654012fSReza Sabdar if ((cp = strchr(save + sp, '/'))) 4732654012fSReza Sabdar *cp = '\0'; 4742654012fSReza Sabdar 4752654012fSReza Sabdar return (save); 4762654012fSReza Sabdar } 4772654012fSReza Sabdar 4782654012fSReza Sabdar /* 4792654012fSReza Sabdar * fs_volexist 4802654012fSReza Sabdar * 4812654012fSReza Sabdar * Check if the volume exists 4822654012fSReza Sabdar */ 4832654012fSReza Sabdar boolean_t 4842654012fSReza Sabdar fs_volexist(char *path) 4852654012fSReza Sabdar { 4862654012fSReza Sabdar struct stat64 st; 4872654012fSReza Sabdar char *p; 4882654012fSReza Sabdar 4892654012fSReza Sabdar if ((p = get_volname(path)) == NULL) 4902654012fSReza Sabdar return (FALSE); 4912654012fSReza Sabdar 4922654012fSReza Sabdar if (stat64(p, &st) != 0) { 4932654012fSReza Sabdar free(p); 4942654012fSReza Sabdar return (FALSE); 4952654012fSReza Sabdar } 4962654012fSReza Sabdar 4972654012fSReza Sabdar free(p); 4982654012fSReza Sabdar return (TRUE); 4992654012fSReza Sabdar } 5002654012fSReza Sabdar 5012654012fSReza Sabdar /* 5022654012fSReza Sabdar * tlm_tarhdr_size 5032654012fSReza Sabdar * 5042654012fSReza Sabdar * Returns the size of the TLM_TAR_HDR structure. 5052654012fSReza Sabdar */ 5062654012fSReza Sabdar int 5072654012fSReza Sabdar tlm_tarhdr_size(void) 5082654012fSReza Sabdar { 5092654012fSReza Sabdar return (sizeof (tlm_tar_hdr_t)); 5102654012fSReza Sabdar } 5112654012fSReza Sabdar 5122654012fSReza Sabdar /* 5132654012fSReza Sabdar * dup_dir_info 5142654012fSReza Sabdar * 5152654012fSReza Sabdar * Make and return a copy of the directory info. 5162654012fSReza Sabdar */ 5172654012fSReza Sabdar struct full_dir_info * 5182654012fSReza Sabdar dup_dir_info(struct full_dir_info *old_dir_info) 5192654012fSReza Sabdar { 5202654012fSReza Sabdar struct full_dir_info *new_dir_info; 5212654012fSReza Sabdar new_dir_info = ndmp_malloc(sizeof (struct full_dir_info)); 5222654012fSReza Sabdar 5232654012fSReza Sabdar if (new_dir_info) { 5242654012fSReza Sabdar bcopy(old_dir_info, new_dir_info, 5252654012fSReza Sabdar sizeof (struct full_dir_info)); 5262654012fSReza Sabdar } 5272654012fSReza Sabdar return (new_dir_info); 5282654012fSReza Sabdar } 5292654012fSReza Sabdar 5302654012fSReza Sabdar /* 5312654012fSReza Sabdar * tlm_new_dir_info 5322654012fSReza Sabdar * 5332654012fSReza Sabdar * Create a new structure, set fh field to what is specified and the path 5342654012fSReza Sabdar * to the concatenation of directory and the component 5352654012fSReza Sabdar */ 5362654012fSReza Sabdar struct full_dir_info * 5372654012fSReza Sabdar tlm_new_dir_info(struct fs_fhandle *fhp, char *dir, char *nm) 5382654012fSReza Sabdar { 5392654012fSReza Sabdar struct full_dir_info *fdip; 5402654012fSReza Sabdar 5412654012fSReza Sabdar if (!(fdip = ndmp_malloc(sizeof (struct full_dir_info)))) 5422654012fSReza Sabdar return (NULL); 5432654012fSReza Sabdar 5442654012fSReza Sabdar (void) memcpy(&fdip->fd_dir_fh, fhp, sizeof (fs_fhandle_t)); 5452654012fSReza Sabdar if (!tlm_cat_path(fdip->fd_dir_name, dir, nm)) { 5462654012fSReza Sabdar free(fdip); 5472654012fSReza Sabdar NDMP_LOG(LOG_DEBUG, "TAPE BACKUP Find> path too long [%s][%s]", 5482654012fSReza Sabdar dir, nm); 5492654012fSReza Sabdar return (NULL); 5502654012fSReza Sabdar } 5512654012fSReza Sabdar return (fdip); 5522654012fSReza Sabdar } 553b6b15642SReza Sabdar 554b6b15642SReza Sabdar /* 555b6b15642SReza Sabdar * sysattr_rdonly 556b6b15642SReza Sabdar * 557b6b15642SReza Sabdar * Check if the attribute file is one of the readonly system 558b6b15642SReza Sabdar * attributes. 559b6b15642SReza Sabdar */ 560b6b15642SReza Sabdar int 561b6b15642SReza Sabdar sysattr_rdonly(char *name) 562b6b15642SReza Sabdar { 563b6b15642SReza Sabdar return (name && strcmp(name, SYSATTR_RDONLY) == 0); 564b6b15642SReza Sabdar } 565b6b15642SReza Sabdar 566b6b15642SReza Sabdar /* 567b6b15642SReza Sabdar * sysattr_rw 568b6b15642SReza Sabdar * 569b6b15642SReza Sabdar * Check if the attribute file is one of the read/write system 570b6b15642SReza Sabdar * attributes. 571b6b15642SReza Sabdar */ 572b6b15642SReza Sabdar int 573b6b15642SReza Sabdar sysattr_rw(char *name) 574b6b15642SReza Sabdar { 575b6b15642SReza Sabdar return (name && strcmp(name, SYSATTR_RW) == 0); 576b6b15642SReza Sabdar } 577