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