xref: /onnv-gate/usr/src/cmd/ndmpd/tlm/tlm_util.c (revision 8540:79dfd3e11c19)
17917SReza.Sabdar@Sun.COM /*
2*8540SReza.Sabdar@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
37917SReza.Sabdar@Sun.COM  * Use is subject to license terms.
47917SReza.Sabdar@Sun.COM  */
57917SReza.Sabdar@Sun.COM 
67917SReza.Sabdar@Sun.COM /*
77917SReza.Sabdar@Sun.COM  * BSD 3 Clause License
87917SReza.Sabdar@Sun.COM  *
97917SReza.Sabdar@Sun.COM  * Copyright (c) 2007, The Storage Networking Industry Association.
107917SReza.Sabdar@Sun.COM  *
117917SReza.Sabdar@Sun.COM  * Redistribution and use in source and binary forms, with or without
127917SReza.Sabdar@Sun.COM  * modification, are permitted provided that the following conditions
137917SReza.Sabdar@Sun.COM  * are met:
147917SReza.Sabdar@Sun.COM  * 	- Redistributions of source code must retain the above copyright
157917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer.
167917SReza.Sabdar@Sun.COM  *
177917SReza.Sabdar@Sun.COM  * 	- Redistributions in binary form must reproduce the above copyright
187917SReza.Sabdar@Sun.COM  *	  notice, this list of conditions and the following disclaimer in
197917SReza.Sabdar@Sun.COM  *	  the documentation and/or other materials provided with the
207917SReza.Sabdar@Sun.COM  *	  distribution.
217917SReza.Sabdar@Sun.COM  *
227917SReza.Sabdar@Sun.COM  *	- Neither the name of The Storage Networking Industry Association (SNIA)
237917SReza.Sabdar@Sun.COM  *	  nor the names of its contributors may be used to endorse or promote
247917SReza.Sabdar@Sun.COM  *	  products derived from this software without specific prior written
257917SReza.Sabdar@Sun.COM  *	  permission.
267917SReza.Sabdar@Sun.COM  *
277917SReza.Sabdar@Sun.COM  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
287917SReza.Sabdar@Sun.COM  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
297917SReza.Sabdar@Sun.COM  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
307917SReza.Sabdar@Sun.COM  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
317917SReza.Sabdar@Sun.COM  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
327917SReza.Sabdar@Sun.COM  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
337917SReza.Sabdar@Sun.COM  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
347917SReza.Sabdar@Sun.COM  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
357917SReza.Sabdar@Sun.COM  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
367917SReza.Sabdar@Sun.COM  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
377917SReza.Sabdar@Sun.COM  * POSSIBILITY OF SUCH DAMAGE.
387917SReza.Sabdar@Sun.COM  */
397917SReza.Sabdar@Sun.COM #include <stdio.h>
407917SReza.Sabdar@Sun.COM #include <stdlib.h>
417917SReza.Sabdar@Sun.COM #include <string.h>
427917SReza.Sabdar@Sun.COM #include <strings.h>
437917SReza.Sabdar@Sun.COM #include <cstack.h>
447917SReza.Sabdar@Sun.COM #include <ctype.h>
457917SReza.Sabdar@Sun.COM #include <tlm.h>
467917SReza.Sabdar@Sun.COM #include "tlm_proto.h"
477917SReza.Sabdar@Sun.COM 
487917SReza.Sabdar@Sun.COM /*
497917SReza.Sabdar@Sun.COM  * Implementation of a list based stack class. The stack only holds
507917SReza.Sabdar@Sun.COM  * pointers/references to application objects. The objects are not
517917SReza.Sabdar@Sun.COM  * copied and the stack never attempts to dereference or access the
527917SReza.Sabdar@Sun.COM  * data objects. Applications should treat cstack_t references as
537917SReza.Sabdar@Sun.COM  * opaque handles.
547917SReza.Sabdar@Sun.COM  */
557917SReza.Sabdar@Sun.COM 
567917SReza.Sabdar@Sun.COM /*
577917SReza.Sabdar@Sun.COM  * cstack_new
587917SReza.Sabdar@Sun.COM  *
597917SReza.Sabdar@Sun.COM  * Allocate and initialize a new stack, which is just an empty cstack_t.
607917SReza.Sabdar@Sun.COM  * A pointer to the new stack is returned. This should be treated as an
617917SReza.Sabdar@Sun.COM  * opaque handle by the caller.
627917SReza.Sabdar@Sun.COM  */
637917SReza.Sabdar@Sun.COM cstack_t *
cstack_new(void)647917SReza.Sabdar@Sun.COM cstack_new(void)
657917SReza.Sabdar@Sun.COM {
667917SReza.Sabdar@Sun.COM 	cstack_t *stk;
677917SReza.Sabdar@Sun.COM 
687917SReza.Sabdar@Sun.COM 	if ((stk = ndmp_malloc(sizeof (cstack_t))) == NULL)
697917SReza.Sabdar@Sun.COM 		return (NULL);
707917SReza.Sabdar@Sun.COM 
717917SReza.Sabdar@Sun.COM 	return (stk);
727917SReza.Sabdar@Sun.COM }
737917SReza.Sabdar@Sun.COM 
747917SReza.Sabdar@Sun.COM 
757917SReza.Sabdar@Sun.COM /*
767917SReza.Sabdar@Sun.COM  * cstack_delete
777917SReza.Sabdar@Sun.COM  *
787917SReza.Sabdar@Sun.COM  * Deallocate the stack. This goes through the list freeing all of the
797917SReza.Sabdar@Sun.COM  * cstack nodes but not the data because we don't know how the data was
807917SReza.Sabdar@Sun.COM  * allocated. A stack really should be empty before it is deleted.
817917SReza.Sabdar@Sun.COM  */
827917SReza.Sabdar@Sun.COM void
cstack_delete(cstack_t * stk)837917SReza.Sabdar@Sun.COM cstack_delete(cstack_t *stk)
847917SReza.Sabdar@Sun.COM {
857917SReza.Sabdar@Sun.COM 	cstack_t *tmp;
867917SReza.Sabdar@Sun.COM 
877917SReza.Sabdar@Sun.COM 	if (stk == NULL) {
887917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cstack_delete: invalid stack");
897917SReza.Sabdar@Sun.COM 		return;
907917SReza.Sabdar@Sun.COM 	}
917917SReza.Sabdar@Sun.COM 
927917SReza.Sabdar@Sun.COM 	while ((tmp = stk->next) != NULL) {
937917SReza.Sabdar@Sun.COM 		stk->next = tmp->next;
947917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cstack_delete(element): 0x%p", tmp);
957917SReza.Sabdar@Sun.COM 		free(tmp);
967917SReza.Sabdar@Sun.COM 	}
977917SReza.Sabdar@Sun.COM 
987917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "cstack_delete: 0x%p", stk);
997917SReza.Sabdar@Sun.COM 	free(stk);
1007917SReza.Sabdar@Sun.COM }
1017917SReza.Sabdar@Sun.COM 
1027917SReza.Sabdar@Sun.COM 
1037917SReza.Sabdar@Sun.COM /*
1047917SReza.Sabdar@Sun.COM  * cstack_push
1057917SReza.Sabdar@Sun.COM  *
1067917SReza.Sabdar@Sun.COM  * Push an element onto the stack. Allocate a new node and assign the
1077917SReza.Sabdar@Sun.COM  * data and len values. We don't care what about the real values of
1087917SReza.Sabdar@Sun.COM  * data or len and we never try to access them. The stack head will
1097917SReza.Sabdar@Sun.COM  * point to the new node.
1107917SReza.Sabdar@Sun.COM  *
1117917SReza.Sabdar@Sun.COM  * Returns 0 on success. Otherwise returns -1 to indicate overflow.
1127917SReza.Sabdar@Sun.COM  */
1137917SReza.Sabdar@Sun.COM int
cstack_push(cstack_t * stk,void * data,int len)1147917SReza.Sabdar@Sun.COM cstack_push(cstack_t *stk, void *data, int len)
1157917SReza.Sabdar@Sun.COM {
1167917SReza.Sabdar@Sun.COM 	cstack_t *stk_node;
1177917SReza.Sabdar@Sun.COM 
1187917SReza.Sabdar@Sun.COM 	if (stk == NULL) {
1197917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cstack_push: invalid stack");
1207917SReza.Sabdar@Sun.COM 		return (-1);
1217917SReza.Sabdar@Sun.COM 	}
1227917SReza.Sabdar@Sun.COM 
1237917SReza.Sabdar@Sun.COM 	if ((stk_node = ndmp_malloc(sizeof (cstack_t))) == NULL)
1247917SReza.Sabdar@Sun.COM 		return (-1);
1257917SReza.Sabdar@Sun.COM 
1267917SReza.Sabdar@Sun.COM 	stk_node->data = data;
1277917SReza.Sabdar@Sun.COM 	stk_node->len = len;
1287917SReza.Sabdar@Sun.COM 	stk_node->next = stk->next;
1297917SReza.Sabdar@Sun.COM 	stk->next = stk_node;
1307917SReza.Sabdar@Sun.COM 
1317917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "cstack_push(0x%p): 0x%p", stk, stk_node);
1327917SReza.Sabdar@Sun.COM 	return (0);
1337917SReza.Sabdar@Sun.COM }
1347917SReza.Sabdar@Sun.COM 
1357917SReza.Sabdar@Sun.COM 
1367917SReza.Sabdar@Sun.COM /*
1377917SReza.Sabdar@Sun.COM  * cstack_pop
1387917SReza.Sabdar@Sun.COM  *
1397917SReza.Sabdar@Sun.COM  * Pop an element off the stack. Set up the data and len references for
1407917SReza.Sabdar@Sun.COM  * the caller, advance the stack head and free the popped stack node.
1417917SReza.Sabdar@Sun.COM  *
1427917SReza.Sabdar@Sun.COM  * Returns 0 on success. Otherwise returns -1 to indicate underflow.
1437917SReza.Sabdar@Sun.COM  */
1447917SReza.Sabdar@Sun.COM int
cstack_pop(cstack_t * stk,void ** data,int * len)1457917SReza.Sabdar@Sun.COM cstack_pop(cstack_t *stk, void **data, int *len)
1467917SReza.Sabdar@Sun.COM {
1477917SReza.Sabdar@Sun.COM 	cstack_t *stk_node;
1487917SReza.Sabdar@Sun.COM 
1497917SReza.Sabdar@Sun.COM 	if (stk == NULL) {
1507917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
1517917SReza.Sabdar@Sun.COM 		return (-1);
1527917SReza.Sabdar@Sun.COM 	}
1537917SReza.Sabdar@Sun.COM 
1547917SReza.Sabdar@Sun.COM 	if ((stk_node = stk->next) == NULL) {
1557917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
1567917SReza.Sabdar@Sun.COM 		return (-1);
1577917SReza.Sabdar@Sun.COM 	}
1587917SReza.Sabdar@Sun.COM 
1597917SReza.Sabdar@Sun.COM 	if (data)
1607917SReza.Sabdar@Sun.COM 		*data = stk_node->data;
1617917SReza.Sabdar@Sun.COM 
1627917SReza.Sabdar@Sun.COM 	if (len)
1637917SReza.Sabdar@Sun.COM 		*len = stk_node->len;
1647917SReza.Sabdar@Sun.COM 
1657917SReza.Sabdar@Sun.COM 	stk->next = stk_node->next;
1667917SReza.Sabdar@Sun.COM 	NDMP_LOG(LOG_DEBUG, "cstack_pop(0x%p): 0x%p", stk, stk_node);
1677917SReza.Sabdar@Sun.COM 
1687917SReza.Sabdar@Sun.COM 	free(stk_node);
1697917SReza.Sabdar@Sun.COM 	return (0);
1707917SReza.Sabdar@Sun.COM }
1717917SReza.Sabdar@Sun.COM 
1727917SReza.Sabdar@Sun.COM /*
1737917SReza.Sabdar@Sun.COM  * cstack_top
1747917SReza.Sabdar@Sun.COM  *
1757917SReza.Sabdar@Sun.COM  * Returns the top data element on the stack without removing it.
1767917SReza.Sabdar@Sun.COM  *
1777917SReza.Sabdar@Sun.COM  * Returns 0 on success. Otherwise returns -1 to indicate underflow.
1787917SReza.Sabdar@Sun.COM  */
1797917SReza.Sabdar@Sun.COM int
cstack_top(cstack_t * stk,void ** data,int * len)1807917SReza.Sabdar@Sun.COM cstack_top(cstack_t *stk, void **data, int *len)
1817917SReza.Sabdar@Sun.COM {
1827917SReza.Sabdar@Sun.COM 	if (stk == NULL) {
1837917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
1847917SReza.Sabdar@Sun.COM 		return (-1);
1857917SReza.Sabdar@Sun.COM 	}
1867917SReza.Sabdar@Sun.COM 
1877917SReza.Sabdar@Sun.COM 	if (stk->next == NULL) {
1887917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
1897917SReza.Sabdar@Sun.COM 		return (-1);
1907917SReza.Sabdar@Sun.COM 	}
1917917SReza.Sabdar@Sun.COM 
1927917SReza.Sabdar@Sun.COM 	if (data)
1937917SReza.Sabdar@Sun.COM 		*data = stk->next->data;
1947917SReza.Sabdar@Sun.COM 
1957917SReza.Sabdar@Sun.COM 	if (len)
1967917SReza.Sabdar@Sun.COM 		*len = stk->next->len;
1977917SReza.Sabdar@Sun.COM 
1987917SReza.Sabdar@Sun.COM 	return (0);
1997917SReza.Sabdar@Sun.COM }
2007917SReza.Sabdar@Sun.COM 
2017917SReza.Sabdar@Sun.COM /*
2027917SReza.Sabdar@Sun.COM  * match
2037917SReza.Sabdar@Sun.COM  *
2047917SReza.Sabdar@Sun.COM  * Matching rules:
2057917SReza.Sabdar@Sun.COM  *	c	Any non-special character matches itslef
2067917SReza.Sabdar@Sun.COM  *	?	Match any character
2077917SReza.Sabdar@Sun.COM  *	ab	character 'a' followed by character 'b'
2087917SReza.Sabdar@Sun.COM  *	S	Any string of non-special characters
2097917SReza.Sabdar@Sun.COM  *	AB	String 'A' followed by string 'B'
2107917SReza.Sabdar@Sun.COM  *	*	Any String, including the empty string
2117917SReza.Sabdar@Sun.COM  */
2127917SReza.Sabdar@Sun.COM boolean_t
match(char * patn,char * str)2137917SReza.Sabdar@Sun.COM match(char *patn, char *str)
2147917SReza.Sabdar@Sun.COM {
2157917SReza.Sabdar@Sun.COM 	for (; ; ) {
2167917SReza.Sabdar@Sun.COM 		switch (*patn) {
2177917SReza.Sabdar@Sun.COM 		case 0:
2187917SReza.Sabdar@Sun.COM 			return (*str == 0);
2197917SReza.Sabdar@Sun.COM 
2207917SReza.Sabdar@Sun.COM 		case '?':
2217917SReza.Sabdar@Sun.COM 			if (*str != 0) {
2227917SReza.Sabdar@Sun.COM 				str++;
2237917SReza.Sabdar@Sun.COM 				patn++;
2247917SReza.Sabdar@Sun.COM 				continue;
2257917SReza.Sabdar@Sun.COM 			} else {
2267917SReza.Sabdar@Sun.COM 				return (FALSE);
2277917SReza.Sabdar@Sun.COM 			}
2287917SReza.Sabdar@Sun.COM 			break;
2297917SReza.Sabdar@Sun.COM 
2307917SReza.Sabdar@Sun.COM 		case '*':
2317917SReza.Sabdar@Sun.COM 			patn++;
2327917SReza.Sabdar@Sun.COM 			if (*patn == 0)
2337917SReza.Sabdar@Sun.COM 				return (TRUE);
2347917SReza.Sabdar@Sun.COM 
2357917SReza.Sabdar@Sun.COM 			while (*str) {
2367917SReza.Sabdar@Sun.COM 				if (match(patn, str))
2377917SReza.Sabdar@Sun.COM 					return (TRUE);
2387917SReza.Sabdar@Sun.COM 				str++;
2397917SReza.Sabdar@Sun.COM 			}
2407917SReza.Sabdar@Sun.COM 			return (FALSE);
2417917SReza.Sabdar@Sun.COM 
2427917SReza.Sabdar@Sun.COM 		default:
2437917SReza.Sabdar@Sun.COM 			if (*str != *patn)
2447917SReza.Sabdar@Sun.COM 				return (FALSE);
2457917SReza.Sabdar@Sun.COM 			str++;
2467917SReza.Sabdar@Sun.COM 			patn++;
2477917SReza.Sabdar@Sun.COM 			continue;
2487917SReza.Sabdar@Sun.COM 		}
2497917SReza.Sabdar@Sun.COM 	}
2507917SReza.Sabdar@Sun.COM }
2517917SReza.Sabdar@Sun.COM 
2527917SReza.Sabdar@Sun.COM /*
2537917SReza.Sabdar@Sun.COM  * Match recursive call
2547917SReza.Sabdar@Sun.COM  */
2557917SReza.Sabdar@Sun.COM int
match_ci(char * patn,char * str)2567917SReza.Sabdar@Sun.COM match_ci(char *patn, char *str)
2577917SReza.Sabdar@Sun.COM {
2587917SReza.Sabdar@Sun.COM 	/*
2597917SReza.Sabdar@Sun.COM 	 * "<" is a special pattern that matches only those names
2607917SReza.Sabdar@Sun.COM 	 * that do NOT have an extension. "." and ".." are ok.
2617917SReza.Sabdar@Sun.COM 	 */
2627917SReza.Sabdar@Sun.COM 	if (strcmp(patn, "<") == 0) {
2637917SReza.Sabdar@Sun.COM 		if ((strcmp(str, ".") == 0) || (strcmp(str, "..") == 0))
2647917SReza.Sabdar@Sun.COM 			return (TRUE);
2657917SReza.Sabdar@Sun.COM 		if (strchr(str, '.') == 0)
2667917SReza.Sabdar@Sun.COM 			return (TRUE);
2677917SReza.Sabdar@Sun.COM 		return (FALSE);
2687917SReza.Sabdar@Sun.COM 	}
2697917SReza.Sabdar@Sun.COM 	for (; ; ) {
2707917SReza.Sabdar@Sun.COM 		switch (*patn) {
2717917SReza.Sabdar@Sun.COM 		case 0:
2727917SReza.Sabdar@Sun.COM 			return (*str == 0);
2737917SReza.Sabdar@Sun.COM 
2747917SReza.Sabdar@Sun.COM 		case '?':
2757917SReza.Sabdar@Sun.COM 			if (*str != 0) {
2767917SReza.Sabdar@Sun.COM 				str++;
2777917SReza.Sabdar@Sun.COM 				patn++;
2787917SReza.Sabdar@Sun.COM 				continue;
2797917SReza.Sabdar@Sun.COM 			} else {
2807917SReza.Sabdar@Sun.COM 				return (FALSE);
2817917SReza.Sabdar@Sun.COM 			}
2827917SReza.Sabdar@Sun.COM 			break;
2837917SReza.Sabdar@Sun.COM 
2847917SReza.Sabdar@Sun.COM 
2857917SReza.Sabdar@Sun.COM 		case '*':
2867917SReza.Sabdar@Sun.COM 			patn++;
2877917SReza.Sabdar@Sun.COM 			if (*patn == 0)
2887917SReza.Sabdar@Sun.COM 				return (TRUE);
2897917SReza.Sabdar@Sun.COM 
2907917SReza.Sabdar@Sun.COM 			while (*str) {
2917917SReza.Sabdar@Sun.COM 				if (match_ci(patn, str))
2927917SReza.Sabdar@Sun.COM 					return (TRUE);
2937917SReza.Sabdar@Sun.COM 				str++;
2947917SReza.Sabdar@Sun.COM 			}
2957917SReza.Sabdar@Sun.COM 			return (FALSE);
2967917SReza.Sabdar@Sun.COM 
2977917SReza.Sabdar@Sun.COM 		default:
2987917SReza.Sabdar@Sun.COM 			if (*str != *patn) {
2997917SReza.Sabdar@Sun.COM 				int	c1 = *str;
3007917SReza.Sabdar@Sun.COM 				int	c2 = *patn;
3017917SReza.Sabdar@Sun.COM 
3027917SReza.Sabdar@Sun.COM 				c1 = tolower(c1);
3037917SReza.Sabdar@Sun.COM 				c2 = tolower(c2);
3047917SReza.Sabdar@Sun.COM 				if (c1 != c2)
3057917SReza.Sabdar@Sun.COM 					return (FALSE);
3067917SReza.Sabdar@Sun.COM 			}
3077917SReza.Sabdar@Sun.COM 			str++;
3087917SReza.Sabdar@Sun.COM 			patn++;
3097917SReza.Sabdar@Sun.COM 			continue;
3107917SReza.Sabdar@Sun.COM 		}
3117917SReza.Sabdar@Sun.COM 	}
3127917SReza.Sabdar@Sun.COM 	/* NOT REACHED */
3137917SReza.Sabdar@Sun.COM }
3147917SReza.Sabdar@Sun.COM 
3157917SReza.Sabdar@Sun.COM /*
3167917SReza.Sabdar@Sun.COM  * Linear matching against a list utility function
3177917SReza.Sabdar@Sun.COM  */
3187917SReza.Sabdar@Sun.COM static boolean_t
parse_match(char line,char * seps)3197917SReza.Sabdar@Sun.COM parse_match(char line, char *seps)
3207917SReza.Sabdar@Sun.COM {
3217917SReza.Sabdar@Sun.COM 	char *sep = seps;
3227917SReza.Sabdar@Sun.COM 
3237917SReza.Sabdar@Sun.COM 	while (*sep != 0) {
3247917SReza.Sabdar@Sun.COM 		/* compare this char with the seperator list */
3257917SReza.Sabdar@Sun.COM 		if (*sep == line)
3267917SReza.Sabdar@Sun.COM 			return (TRUE);
3277917SReza.Sabdar@Sun.COM 		sep++;
3287917SReza.Sabdar@Sun.COM 	}
3297917SReza.Sabdar@Sun.COM 	return (FALSE);
3307917SReza.Sabdar@Sun.COM }
3317917SReza.Sabdar@Sun.COM 
3327917SReza.Sabdar@Sun.COM /*
3337917SReza.Sabdar@Sun.COM  * Returns the next entry of the list after
3347917SReza.Sabdar@Sun.COM  * each separator
3357917SReza.Sabdar@Sun.COM  */
3367917SReza.Sabdar@Sun.COM char *
parse(char ** line,char * seps)3377917SReza.Sabdar@Sun.COM parse(char **line, char *seps)
3387917SReza.Sabdar@Sun.COM {
3397917SReza.Sabdar@Sun.COM 	char *start = *line;
3407917SReza.Sabdar@Sun.COM 
3417917SReza.Sabdar@Sun.COM 	while (**line != 0) {
3427917SReza.Sabdar@Sun.COM 		*line = *line + 1;
3437917SReza.Sabdar@Sun.COM 		if (parse_match(**line, seps)) {
3447917SReza.Sabdar@Sun.COM 			/* hit a terminator, skip trailing terminators */
3457917SReza.Sabdar@Sun.COM 			while (parse_match(**line, seps)) {
3467917SReza.Sabdar@Sun.COM 				**line = 0;
3477917SReza.Sabdar@Sun.COM 				*line = *line + 1;
3487917SReza.Sabdar@Sun.COM 			}
3497917SReza.Sabdar@Sun.COM 			break;
3507917SReza.Sabdar@Sun.COM 		}
3517917SReza.Sabdar@Sun.COM 	}
3527917SReza.Sabdar@Sun.COM 	return (start);
3537917SReza.Sabdar@Sun.COM }
3547917SReza.Sabdar@Sun.COM 
3557917SReza.Sabdar@Sun.COM /*
3567917SReza.Sabdar@Sun.COM  * oct_atoi
3577917SReza.Sabdar@Sun.COM  *
3587917SReza.Sabdar@Sun.COM  * Convert an octal string to integer
3597917SReza.Sabdar@Sun.COM  */
3607917SReza.Sabdar@Sun.COM int
oct_atoi(char * p)3617917SReza.Sabdar@Sun.COM oct_atoi(char *p)
3627917SReza.Sabdar@Sun.COM {
3637917SReza.Sabdar@Sun.COM 	int v = 0;
3647917SReza.Sabdar@Sun.COM 	int c;
3657917SReza.Sabdar@Sun.COM 
3667917SReza.Sabdar@Sun.COM 	while (*p == ' ')
3677917SReza.Sabdar@Sun.COM 		p++;
3687917SReza.Sabdar@Sun.COM 
3697917SReza.Sabdar@Sun.COM 	while ('0' <= (c = *p++) && c <= '7') {
3707917SReza.Sabdar@Sun.COM 		v <<= 3;
3717917SReza.Sabdar@Sun.COM 		v += c - '0';
3727917SReza.Sabdar@Sun.COM 	}
3737917SReza.Sabdar@Sun.COM 
3747917SReza.Sabdar@Sun.COM 	return (v);
3757917SReza.Sabdar@Sun.COM }
3767917SReza.Sabdar@Sun.COM 
3777917SReza.Sabdar@Sun.COM /*
3787917SReza.Sabdar@Sun.COM  * strupr
3797917SReza.Sabdar@Sun.COM  *
3807917SReza.Sabdar@Sun.COM  * Convert a string to uppercase using the appropriate codepage. The
3817917SReza.Sabdar@Sun.COM  * string is converted in place. A pointer to the string is returned.
3827917SReza.Sabdar@Sun.COM  * There is an assumption here that uppercase and lowercase values
3837917SReza.Sabdar@Sun.COM  * always result encode to the same length.
3847917SReza.Sabdar@Sun.COM  */
3857917SReza.Sabdar@Sun.COM char *
strupr(char * s)3867917SReza.Sabdar@Sun.COM strupr(char *s)
3877917SReza.Sabdar@Sun.COM {
3887917SReza.Sabdar@Sun.COM 	char c;
3897917SReza.Sabdar@Sun.COM 	unsigned char *p = (unsigned char *)s;
3907917SReza.Sabdar@Sun.COM 
3917917SReza.Sabdar@Sun.COM 	while (*p) {
3927917SReza.Sabdar@Sun.COM 		c = toupper(*p);
3937917SReza.Sabdar@Sun.COM 		*p++ = c;
3947917SReza.Sabdar@Sun.COM 	}
3957917SReza.Sabdar@Sun.COM 	return (s);
3967917SReza.Sabdar@Sun.COM }
3977917SReza.Sabdar@Sun.COM 
3987917SReza.Sabdar@Sun.COM /*
3997917SReza.Sabdar@Sun.COM  * trim_whitespace
4007917SReza.Sabdar@Sun.COM  *
4017917SReza.Sabdar@Sun.COM  * Trim leading and trailing whitespace chars(as defined by isspace)
4027917SReza.Sabdar@Sun.COM  * from a buffer. Example; if the input buffer contained "  text  ",
4037917SReza.Sabdar@Sun.COM  * it will contain "text", when we return. We assume that the buffer
4047917SReza.Sabdar@Sun.COM  * contains a null terminated string. A pointer to the buffer is
4057917SReza.Sabdar@Sun.COM  * returned.
4067917SReza.Sabdar@Sun.COM  */
4077917SReza.Sabdar@Sun.COM char *
trim_whitespace(char * buf)4087917SReza.Sabdar@Sun.COM trim_whitespace(char *buf)
4097917SReza.Sabdar@Sun.COM {
4107917SReza.Sabdar@Sun.COM 	char *p = buf;
4117917SReza.Sabdar@Sun.COM 	char *q = buf;
4127917SReza.Sabdar@Sun.COM 
4137917SReza.Sabdar@Sun.COM 	if (buf == 0)
4147917SReza.Sabdar@Sun.COM 		return (0);
4157917SReza.Sabdar@Sun.COM 
4167917SReza.Sabdar@Sun.COM 	while (*p && isspace(*p))
4177917SReza.Sabdar@Sun.COM 		++p;
4187917SReza.Sabdar@Sun.COM 
4197917SReza.Sabdar@Sun.COM 	while ((*q = *p++) != 0)
4207917SReza.Sabdar@Sun.COM 		++q;
4217917SReza.Sabdar@Sun.COM 
4227917SReza.Sabdar@Sun.COM 	if (q != buf) {
4237917SReza.Sabdar@Sun.COM 		while ((--q, isspace(*q)) != 0)
4247917SReza.Sabdar@Sun.COM 			*q = '\0';
4257917SReza.Sabdar@Sun.COM 	}
4267917SReza.Sabdar@Sun.COM 
4277917SReza.Sabdar@Sun.COM 	return (buf);
4287917SReza.Sabdar@Sun.COM }
4297917SReza.Sabdar@Sun.COM 
4307917SReza.Sabdar@Sun.COM /*
4317917SReza.Sabdar@Sun.COM  * trim_name
4327917SReza.Sabdar@Sun.COM  *
4337917SReza.Sabdar@Sun.COM  * Trims the slash and dot slash from the beginning of the
4347917SReza.Sabdar@Sun.COM  * path name.
4357917SReza.Sabdar@Sun.COM  */
4367917SReza.Sabdar@Sun.COM char *
trim_name(char * nm)4377917SReza.Sabdar@Sun.COM trim_name(char *nm)
4387917SReza.Sabdar@Sun.COM {
4397917SReza.Sabdar@Sun.COM 	while (*nm) {
4407917SReza.Sabdar@Sun.COM 		if (*nm == '/') {
4417917SReza.Sabdar@Sun.COM 			nm++;
4427917SReza.Sabdar@Sun.COM 			continue;
4437917SReza.Sabdar@Sun.COM 		}
4447917SReza.Sabdar@Sun.COM 		if (*nm == '.' && nm[1] == '/' && nm[2]) {
4457917SReza.Sabdar@Sun.COM 			nm += 2;
4467917SReza.Sabdar@Sun.COM 			continue;
4477917SReza.Sabdar@Sun.COM 		}
4487917SReza.Sabdar@Sun.COM 		break;
4497917SReza.Sabdar@Sun.COM 	}
4507917SReza.Sabdar@Sun.COM 	return (nm);
4517917SReza.Sabdar@Sun.COM }
4527917SReza.Sabdar@Sun.COM 
4537917SReza.Sabdar@Sun.COM /*
4547917SReza.Sabdar@Sun.COM  * get_volname
4557917SReza.Sabdar@Sun.COM  *
4567917SReza.Sabdar@Sun.COM  * Extract the volume name from the path
4577917SReza.Sabdar@Sun.COM  */
4587917SReza.Sabdar@Sun.COM char *
get_volname(char * path)4597917SReza.Sabdar@Sun.COM get_volname(char *path)
4607917SReza.Sabdar@Sun.COM {
4617917SReza.Sabdar@Sun.COM 	char *cp, *save;
4627917SReza.Sabdar@Sun.COM 	int sp;
4637917SReza.Sabdar@Sun.COM 
4647917SReza.Sabdar@Sun.COM 	if (!path)
4657917SReza.Sabdar@Sun.COM 		return (NULL);
4667917SReza.Sabdar@Sun.COM 
4677917SReza.Sabdar@Sun.COM 	if (!(save = strdup(path)))
4687917SReza.Sabdar@Sun.COM 		return (NULL);
4697917SReza.Sabdar@Sun.COM 
4707917SReza.Sabdar@Sun.COM 	sp = strspn(path, "/");
4717917SReza.Sabdar@Sun.COM 	if (*(path + sp) == '\0') {
4727917SReza.Sabdar@Sun.COM 		free(save);
4737917SReza.Sabdar@Sun.COM 		return (NULL);
4747917SReza.Sabdar@Sun.COM 	}
4757917SReza.Sabdar@Sun.COM 
4767917SReza.Sabdar@Sun.COM 	if ((cp = strchr(save + sp, '/')))
4777917SReza.Sabdar@Sun.COM 		*cp = '\0';
4787917SReza.Sabdar@Sun.COM 
4797917SReza.Sabdar@Sun.COM 	return (save);
4807917SReza.Sabdar@Sun.COM }
4817917SReza.Sabdar@Sun.COM 
4827917SReza.Sabdar@Sun.COM /*
4837917SReza.Sabdar@Sun.COM  * fs_volexist
4847917SReza.Sabdar@Sun.COM  *
4857917SReza.Sabdar@Sun.COM  * Check if the volume exists
4867917SReza.Sabdar@Sun.COM  */
4877917SReza.Sabdar@Sun.COM boolean_t
fs_volexist(char * path)4887917SReza.Sabdar@Sun.COM fs_volexist(char *path)
4897917SReza.Sabdar@Sun.COM {
4907917SReza.Sabdar@Sun.COM 	struct stat64 st;
4917917SReza.Sabdar@Sun.COM 	char *p;
4927917SReza.Sabdar@Sun.COM 
4937917SReza.Sabdar@Sun.COM 	if ((p = get_volname(path)) == NULL)
4947917SReza.Sabdar@Sun.COM 		return (FALSE);
4957917SReza.Sabdar@Sun.COM 
4967917SReza.Sabdar@Sun.COM 	if (stat64(p, &st) != 0) {
4977917SReza.Sabdar@Sun.COM 		free(p);
4987917SReza.Sabdar@Sun.COM 		return (FALSE);
4997917SReza.Sabdar@Sun.COM 	}
5007917SReza.Sabdar@Sun.COM 
5017917SReza.Sabdar@Sun.COM 	free(p);
5027917SReza.Sabdar@Sun.COM 	return (TRUE);
5037917SReza.Sabdar@Sun.COM }
5047917SReza.Sabdar@Sun.COM 
5057917SReza.Sabdar@Sun.COM /*
5067917SReza.Sabdar@Sun.COM  * tlm_tarhdr_size
5077917SReza.Sabdar@Sun.COM  *
5087917SReza.Sabdar@Sun.COM  * Returns the size of the TLM_TAR_HDR structure.
5097917SReza.Sabdar@Sun.COM  */
5107917SReza.Sabdar@Sun.COM int
tlm_tarhdr_size(void)5117917SReza.Sabdar@Sun.COM tlm_tarhdr_size(void)
5127917SReza.Sabdar@Sun.COM {
5137917SReza.Sabdar@Sun.COM 	return (sizeof (tlm_tar_hdr_t));
5147917SReza.Sabdar@Sun.COM }
5157917SReza.Sabdar@Sun.COM 
5167917SReza.Sabdar@Sun.COM /*
5177917SReza.Sabdar@Sun.COM  * dup_dir_info
5187917SReza.Sabdar@Sun.COM  *
5197917SReza.Sabdar@Sun.COM  * Make and return a copy of the directory info.
5207917SReza.Sabdar@Sun.COM  */
5217917SReza.Sabdar@Sun.COM struct full_dir_info *
dup_dir_info(struct full_dir_info * old_dir_info)5227917SReza.Sabdar@Sun.COM dup_dir_info(struct full_dir_info *old_dir_info)
5237917SReza.Sabdar@Sun.COM {
5247917SReza.Sabdar@Sun.COM 	struct	full_dir_info *new_dir_info;
5257917SReza.Sabdar@Sun.COM 	new_dir_info = ndmp_malloc(sizeof (struct full_dir_info));
5267917SReza.Sabdar@Sun.COM 
5277917SReza.Sabdar@Sun.COM 	if (new_dir_info) {
5287917SReza.Sabdar@Sun.COM 		bcopy(old_dir_info, new_dir_info,
5297917SReza.Sabdar@Sun.COM 		    sizeof (struct full_dir_info));
5307917SReza.Sabdar@Sun.COM 	}
5317917SReza.Sabdar@Sun.COM 	return (new_dir_info);
5327917SReza.Sabdar@Sun.COM }
5337917SReza.Sabdar@Sun.COM 
5347917SReza.Sabdar@Sun.COM /*
5357917SReza.Sabdar@Sun.COM  * tlm_new_dir_info
5367917SReza.Sabdar@Sun.COM  *
5377917SReza.Sabdar@Sun.COM  * Create a new structure, set fh field to what is specified and the path
5387917SReza.Sabdar@Sun.COM  * to the concatenation of directory and the component
5397917SReza.Sabdar@Sun.COM  */
5407917SReza.Sabdar@Sun.COM struct full_dir_info *
tlm_new_dir_info(struct fs_fhandle * fhp,char * dir,char * nm)5417917SReza.Sabdar@Sun.COM tlm_new_dir_info(struct  fs_fhandle *fhp, char *dir, char *nm)
5427917SReza.Sabdar@Sun.COM {
5437917SReza.Sabdar@Sun.COM 	struct full_dir_info *fdip;
5447917SReza.Sabdar@Sun.COM 
5457917SReza.Sabdar@Sun.COM 	if (!(fdip = ndmp_malloc(sizeof (struct full_dir_info))))
5467917SReza.Sabdar@Sun.COM 		return (NULL);
5477917SReza.Sabdar@Sun.COM 
5487917SReza.Sabdar@Sun.COM 	(void) memcpy(&fdip->fd_dir_fh, fhp, sizeof (fs_fhandle_t));
5497917SReza.Sabdar@Sun.COM 	if (!tlm_cat_path(fdip->fd_dir_name, dir, nm)) {
5507917SReza.Sabdar@Sun.COM 		free(fdip);
5517917SReza.Sabdar@Sun.COM 		NDMP_LOG(LOG_DEBUG, "TAPE BACKUP Find> path too long [%s][%s]",
5527917SReza.Sabdar@Sun.COM 		    dir, nm);
5537917SReza.Sabdar@Sun.COM 		return (NULL);
5547917SReza.Sabdar@Sun.COM 	}
5557917SReza.Sabdar@Sun.COM 	return (fdip);
5567917SReza.Sabdar@Sun.COM }
557*8540SReza.Sabdar@Sun.COM 
558*8540SReza.Sabdar@Sun.COM /*
559*8540SReza.Sabdar@Sun.COM  * sysattr_rdonly
560*8540SReza.Sabdar@Sun.COM  *
561*8540SReza.Sabdar@Sun.COM  * Check if the attribute file is one of the readonly system
562*8540SReza.Sabdar@Sun.COM  * attributes.
563*8540SReza.Sabdar@Sun.COM  */
564*8540SReza.Sabdar@Sun.COM int
sysattr_rdonly(char * name)565*8540SReza.Sabdar@Sun.COM sysattr_rdonly(char *name)
566*8540SReza.Sabdar@Sun.COM {
567*8540SReza.Sabdar@Sun.COM 	return (name && strcmp(name, SYSATTR_RDONLY) == 0);
568*8540SReza.Sabdar@Sun.COM }
569*8540SReza.Sabdar@Sun.COM 
570*8540SReza.Sabdar@Sun.COM /*
571*8540SReza.Sabdar@Sun.COM  * sysattr_rw
572*8540SReza.Sabdar@Sun.COM  *
573*8540SReza.Sabdar@Sun.COM  * Check if the attribute file is one of the read/write system
574*8540SReza.Sabdar@Sun.COM  * attributes.
575*8540SReza.Sabdar@Sun.COM  */
576*8540SReza.Sabdar@Sun.COM int
sysattr_rw(char * name)577*8540SReza.Sabdar@Sun.COM sysattr_rw(char *name)
578*8540SReza.Sabdar@Sun.COM {
579*8540SReza.Sabdar@Sun.COM 	return (name && strcmp(name, SYSATTR_RW) == 0);
580*8540SReza.Sabdar@Sun.COM }
581