xref: /titanic_52/usr/src/cmd/ndmpd/tlm/tlm_util.c (revision 33f5ff17089e3a43e6e730bf80384c233123dbd9)
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