2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 * Copyright 2012 Milan Jurik. All rights reserved.
10 * Copyright (c) 2007, The Storage Networking Industry Association.
12 * Redistribution and use in source and binary forms, with or without
13 * modification, are permitted provided that the following conditions
15 * - Redistributions of source code must retain the above copyright
16 * notice, this list of conditions and the following disclaimer.
18 * - Redistributions in binary form must reproduce the above copyright
19 * notice, this list of conditions and the following disclaimer in
20 * the documentation and/or other materials provided with the
23 * - Neither the name of The Storage Networking Industry Association (SNIA)
24 * nor the names of its contributors may be used to endorse or promote
25 * products derived from this software without specific prior written
28 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
29 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
30 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
31 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
32 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
33 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
34 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
35 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
36 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
37 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
38 * POSSIBILITY OF SUCH DAMAGE.
47 #include "tlm_proto.h"
50 * Implementation of a list based stack class. The stack only holds
51 * pointers/references to application objects. The objects are not
52 * copied and the stack never attempts to dereference or access the
53 * data objects. Applications should treat cstack_t references as
60 * Allocate and initialize a new stack, which is just an empty cstack_t.
61 * A pointer to the new stack is returned. This should be treated as an
62 * opaque handle by the caller.
69 if ((stk
= ndmp_malloc(sizeof (cstack_t
))) == NULL
)
79 * Deallocate the stack. This goes through the list freeing all of the
80 * cstack nodes but not the data because we don't know how the data was
81 * allocated. A stack really should be empty before it is deleted.
84 cstack_delete(cstack_t
*stk
)
89 NDMP_LOG(LOG_DEBUG
, "cstack_delete: invalid stack");
93 while ((tmp
= stk
->next
) != NULL
) {
94 stk
->next
= tmp
->next
;
95 NDMP_LOG(LOG_DEBUG
, "cstack_delete(element): 0x%p", tmp
);
99 NDMP_LOG(LOG_DEBUG
, "cstack_delete: 0x%p", stk
);
107 * Push an element onto the stack. Allocate a new node and assign the
108 * data and len values. We don't care what about the real values of
109 * data or len and we never try to access them. The stack head will
110 * point to the new node.
112 * Returns 0 on success. Otherwise returns -1 to indicate overflow.
115 cstack_push(cstack_t
*stk
, void *data
, int len
)
120 NDMP_LOG(LOG_DEBUG
, "cstack_push: invalid stack");
124 if ((stk_node
= ndmp_malloc(sizeof (cstack_t
))) == NULL
)
127 stk_node
->data
= data
;
129 stk_node
->next
= stk
->next
;
130 stk
->next
= stk_node
;
132 NDMP_LOG(LOG_DEBUG
, "cstack_push(0x%p): 0x%p", stk
, stk_node
);
140 * Pop an element off the stack. Set up the data and len references for
141 * the caller, advance the stack head and free the popped stack node.
143 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
146 cstack_pop(cstack_t
*stk
, void **data
, int *len
)
151 NDMP_LOG(LOG_DEBUG
, "cstack_pop: invalid stack");
155 if ((stk_node
= stk
->next
) == NULL
) {
156 NDMP_LOG(LOG_DEBUG
, "cstack_pop: underflow");
161 *data
= stk_node
->data
;
164 *len
= stk_node
->len
;
166 stk
->next
= stk_node
->next
;
167 NDMP_LOG(LOG_DEBUG
, "cstack_pop(0x%p): 0x%p", stk
, stk_node
);
176 * Returns the top data element on the stack without removing it.
178 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
181 cstack_top(cstack_t
*stk
, void **data
, int *len
)
184 NDMP_LOG(LOG_DEBUG
, "cstack_pop: invalid stack");
188 if (stk
->next
== NULL
) {
189 NDMP_LOG(LOG_DEBUG
, "cstack_pop: underflow");
194 *data
= stk
->next
->data
;
197 *len
= stk
->next
->len
;
206 * c Any non-special character matches itslef
207 * ? Match any character
208 * ab character 'a' followed by character 'b'
209 * S Any string of non-special characters
210 * AB String 'A' followed by string 'B'
211 * * Any String, including the empty string
214 match(char *patn
, char *str
)
235 if (match(patn
, str
))
252 * Match recursive call
255 match_ci(char *patn
, char *str
)
258 * "<" is a special pattern that matches only those names
259 * that do NOT have an extension. "." and ".." are ok.
261 if (strcmp(patn
, "<") == 0) {
262 if ((strcmp(str
, ".") == 0) || (strcmp(str
, "..") == 0))
264 if (strchr(str
, '.') == 0)
287 if (match_ci(patn
, str
))
312 * Linear matching against a list utility function
315 parse_match(char line
, char *seps
)
320 /* compare this char with the seperator list */
329 * Returns the next entry of the list after
333 parse(char **line
, char *seps
)
337 while (**line
!= 0) {
339 if (parse_match(**line
, seps
)) {
340 /* hit a terminator, skip trailing terminators */
341 while (parse_match(**line
, seps
)) {
354 * Convert an octal string to integer
365 while ('0' <= (c
= *p
++) && c
<= '7') {
376 * Convert a string to uppercase using the appropriate codepage. The
377 * string is converted in place. A pointer to the string is returned.
378 * There is an assumption here that uppercase and lowercase values
379 * always result encode to the same length.
385 unsigned char *p
= (unsigned char *)s
;
397 * Trim leading and trailing whitespace chars(as defined by isspace)
398 * from a buffer. Example; if the input buffer contained " text ",
399 * it will contain "text", when we return. We assume that the buffer
400 * contains a null terminated string. A pointer to the buffer is
404 trim_whitespace(char *buf
)
412 while (*p
&& isspace(*p
))
415 while ((*q
= *p
++) != 0)
419 while ((--q
, isspace(*q
)) != 0)
429 * Trims the slash and dot slash from the beginning of the
440 if (*nm
== '.' && nm
[1] == '/' && nm
[2]) {
452 * Extract the volume name from the path
455 get_volname(char *path
)
463 if (!(save
= strdup(path
)))
466 sp
= strspn(path
, "/");
467 if (*(path
+ sp
) == '\0') {
472 if ((cp
= strchr(save
+ sp
, '/')))
481 * Check if the volume exists
484 fs_volexist(char *path
)
489 if ((p
= get_volname(path
)) == NULL
)
492 if (stat64(p
, &st
) != 0) {
504 * Returns the size of the TLM_TAR_HDR structure.
507 tlm_tarhdr_size(void)
509 return (sizeof (tlm_tar_hdr_t
));
515 * Make and return a copy of the directory info.
517 struct full_dir_info
*
518 dup_dir_info(struct full_dir_info
*old_dir_info
)
520 struct full_dir_info
*new_dir_info
;
521 new_dir_info
= ndmp_malloc(sizeof (struct full_dir_info
));
524 bcopy(old_dir_info
, new_dir_info
,
525 sizeof (struct full_dir_info
));
527 return (new_dir_info
);
533 * Create a new structure, set fh field to what is specified and the path
534 * to the concatenation of directory and the component
536 struct full_dir_info
*
537 tlm_new_dir_info(struct fs_fhandle
*fhp
, char *dir
, char *nm
)
539 struct full_dir_info
*fdip
;
541 if (!(fdip
= ndmp_malloc(sizeof (struct full_dir_info
))))
544 (void) memcpy(&fdip
->fd_dir_fh
, fhp
, sizeof (fs_fhandle_t
));
545 if (!tlm_cat_path(fdip
->fd_dir_name
, dir
, nm
)) {
547 NDMP_LOG(LOG_DEBUG
, "TAPE BACKUP Find> path too long [%s][%s]",
557 * Check if the attribute file is one of the readonly system
561 sysattr_rdonly(char *name
)
563 return (name
&& strcmp(name
, SYSATTR_RDONLY
) == 0);
569 * Check if the attribute file is one of the read/write system
573 sysattr_rw(char *name
)
575 return (name
&& strcmp(name
, SYSATTR_RW
) == 0);