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 *
cstack_new(void)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
cstack_delete(cstack_t * stk)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
cstack_push(cstack_t * stk,void * data,int len)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
cstack_pop(cstack_t * stk,void ** data,int * len)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
cstack_top(cstack_t * stk,void ** data,int * len)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
match(char * patn,char * str)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
match_ci(char * patn,char * str)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
parse_match(char line,char * seps)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 *
parse(char ** line,char * seps)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
oct_atoi(char * p)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 *
strupr(char * s)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 *
trim_whitespace(char * buf)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 *
trim_name(char * nm)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 *
get_volname(char * path)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
fs_volexist(char * path)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
tlm_tarhdr_size(void)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 *
dup_dir_info(struct full_dir_info * old_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 *
tlm_new_dir_info(struct fs_fhandle * fhp,char * dir,char * nm)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
sysattr_rdonly(char * name)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
sysattr_rw(char * name)573b6b15642SReza Sabdar sysattr_rw(char *name)
574b6b15642SReza Sabdar {
575b6b15642SReza Sabdar return (name && strcmp(name, SYSATTR_RW) == 0);
576b6b15642SReza Sabdar }
577