20 * the documentation and/or other materials provided with the
21 * distribution.
22 *
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
26 * permission.
27 *
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.
39 */
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <strings.h>
44 #include <cstack.h>
45 #include <ctype.h>
46 #include <tlm.h>
47 #include "tlm_proto.h"
48
49 /*
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
54 * opaque handles.
55 */
56
57 /*
58 * cstack_new
59 *
69 if ((stk = ndmp_malloc(sizeof (cstack_t))) == NULL)
70 return (NULL);
71
72 return (stk);
73 }
74
75
76 /*
77 * cstack_delete
78 *
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.
82 */
83 void
84 cstack_delete(cstack_t *stk)
85 {
86 cstack_t *tmp;
87
88 if (stk == NULL) {
89 NDMP_LOG(LOG_DEBUG, "cstack_delete: invalid stack");
90 return;
91 }
92
93 while ((tmp = stk->next) != NULL) {
94 stk->next = tmp->next;
95 NDMP_LOG(LOG_DEBUG, "cstack_delete(element): 0x%p", tmp);
96 free(tmp);
97 }
98
99 NDMP_LOG(LOG_DEBUG, "cstack_delete: 0x%p", stk);
100 free(stk);
101 }
102
103
104 /*
105 * cstack_push
106 *
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.
111 *
112 * Returns 0 on success. Otherwise returns -1 to indicate overflow.
113 */
114 int
115 cstack_push(cstack_t *stk, void *data, int len)
116 {
117 cstack_t *stk_node;
118
119 if (stk == NULL) {
120 NDMP_LOG(LOG_DEBUG, "cstack_push: invalid stack");
121 return (-1);
122 }
123
124 if ((stk_node = ndmp_malloc(sizeof (cstack_t))) == NULL)
125 return (-1);
126
127 stk_node->data = data;
128 stk_node->len = len;
129 stk_node->next = stk->next;
130 stk->next = stk_node;
131
132 NDMP_LOG(LOG_DEBUG, "cstack_push(0x%p): 0x%p", stk, stk_node);
133 return (0);
134 }
135
136
137 /*
138 * cstack_pop
139 *
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.
142 *
143 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
144 */
145 int
146 cstack_pop(cstack_t *stk, void **data, int *len)
147 {
148 cstack_t *stk_node;
149
150 if (stk == NULL) {
151 NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
152 return (-1);
153 }
154
155 if ((stk_node = stk->next) == NULL) {
156 NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
157 return (-1);
158 }
159
160 if (data)
161 *data = stk_node->data;
162
163 if (len)
164 *len = stk_node->len;
165
166 stk->next = stk_node->next;
167 NDMP_LOG(LOG_DEBUG, "cstack_pop(0x%p): 0x%p", stk, stk_node);
168
169 free(stk_node);
170 return (0);
171 }
172
173 /*
174 * cstack_top
175 *
176 * Returns the top data element on the stack without removing it.
177 *
178 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
179 */
180 int
181 cstack_top(cstack_t *stk, void **data, int *len)
182 {
183 if (stk == NULL) {
184 NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
185 return (-1);
186 }
187
188 if (stk->next == NULL) {
189 NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
190 return (-1);
191 }
192
193 if (data)
194 *data = stk->next->data;
195
196 if (len)
197 *len = stk->next->len;
198
199 return (0);
200 }
201
202 /*
203 * match
204 *
205 * Matching rules:
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
527 return (new_dir_info);
528 }
529
530 /*
531 * tlm_new_dir_info
532 *
533 * Create a new structure, set fh field to what is specified and the path
534 * to the concatenation of directory and the component
535 */
536 struct full_dir_info *
537 tlm_new_dir_info(struct fs_fhandle *fhp, char *dir, char *nm)
538 {
539 struct full_dir_info *fdip;
540
541 if (!(fdip = ndmp_malloc(sizeof (struct full_dir_info))))
542 return (NULL);
543
544 (void) memcpy(&fdip->fd_dir_fh, fhp, sizeof (fs_fhandle_t));
545 if (!tlm_cat_path(fdip->fd_dir_name, dir, nm)) {
546 free(fdip);
547 NDMP_LOG(LOG_DEBUG, "TAPE BACKUP Find> path too long [%s][%s]",
548 dir, nm);
549 return (NULL);
550 }
551 return (fdip);
552 }
553
554 /*
555 * sysattr_rdonly
556 *
557 * Check if the attribute file is one of the readonly system
558 * attributes.
559 */
560 int
561 sysattr_rdonly(char *name)
562 {
563 return (name && strcmp(name, SYSATTR_RDONLY) == 0);
564 }
565
566 /*
567 * sysattr_rw
|
20 * the documentation and/or other materials provided with the
21 * distribution.
22 *
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
26 * permission.
27 *
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.
39 */
40 /* Copyright 2016 Nexenta Systems, Inc. All rights reserved. */
41
42 #include <syslog.h>
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <strings.h>
47 #include <cstack.h>
48 #include <ctype.h>
49 #include <tlm.h>
50 #include "tlm_proto.h"
51
52 /*
53 * Implementation of a list based stack class. The stack only holds
54 * pointers/references to application objects. The objects are not
55 * copied and the stack never attempts to dereference or access the
56 * data objects. Applications should treat cstack_t references as
57 * opaque handles.
58 */
59
60 /*
61 * cstack_new
62 *
72 if ((stk = ndmp_malloc(sizeof (cstack_t))) == NULL)
73 return (NULL);
74
75 return (stk);
76 }
77
78
79 /*
80 * cstack_delete
81 *
82 * Deallocate the stack. This goes through the list freeing all of the
83 * cstack nodes but not the data because we don't know how the data was
84 * allocated. A stack really should be empty before it is deleted.
85 */
86 void
87 cstack_delete(cstack_t *stk)
88 {
89 cstack_t *tmp;
90
91 if (stk == NULL) {
92 return;
93 }
94
95 while ((tmp = stk->next) != NULL) {
96 stk->next = tmp->next;
97 free(tmp);
98 }
99
100 free(stk);
101 }
102
103
104 /*
105 * cstack_push
106 *
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.
111 *
112 * Returns 0 on success. Otherwise returns -1 to indicate overflow.
113 */
114 int
115 cstack_push(cstack_t *stk, void *data, int len)
116 {
117 cstack_t *stk_node;
118
119 if (stk == NULL) {
120 return (-1);
121 }
122
123 if ((stk_node = ndmp_malloc(sizeof (cstack_t))) == NULL)
124 return (-1);
125
126 stk_node->data = data;
127 stk_node->len = len;
128 stk_node->next = stk->next;
129 stk->next = stk_node;
130
131 return (0);
132 }
133
134
135 /*
136 * cstack_pop
137 *
138 * Pop an element off the stack. Set up the data and len references for
139 * the caller, advance the stack head and free the popped stack node.
140 *
141 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
142 */
143 int
144 cstack_pop(cstack_t *stk, void **data, int *len)
145 {
146 cstack_t *stk_node;
147
148 if (stk == NULL) {
149 return (-1);
150 }
151
152 if ((stk_node = stk->next) == NULL) {
153 return (-1);
154 }
155
156 if (data)
157 *data = stk_node->data;
158
159 if (len)
160 *len = stk_node->len;
161
162 stk->next = stk_node->next;
163
164 free(stk_node);
165 return (0);
166 }
167
168 /*
169 * cstack_top
170 *
171 * Returns the top data element on the stack without removing it.
172 *
173 * Returns 0 on success. Otherwise returns -1 to indicate underflow.
174 */
175 int
176 cstack_top(cstack_t *stk, void **data, int *len)
177 {
178 if (stk == NULL) {
179 return (-1);
180 }
181
182 if (stk->next == NULL) {
183 return (-1);
184 }
185
186 if (data)
187 *data = stk->next->data;
188
189 if (len)
190 *len = stk->next->len;
191
192 return (0);
193 }
194
195 /*
196 * match
197 *
198 * Matching rules:
199 * c Any non-special character matches itslef
200 * ? Match any character
201 * ab character 'a' followed by character 'b'
202 * S Any string of non-special characters
520 return (new_dir_info);
521 }
522
523 /*
524 * tlm_new_dir_info
525 *
526 * Create a new structure, set fh field to what is specified and the path
527 * to the concatenation of directory and the component
528 */
529 struct full_dir_info *
530 tlm_new_dir_info(struct fs_fhandle *fhp, char *dir, char *nm)
531 {
532 struct full_dir_info *fdip;
533
534 if (!(fdip = ndmp_malloc(sizeof (struct full_dir_info))))
535 return (NULL);
536
537 (void) memcpy(&fdip->fd_dir_fh, fhp, sizeof (fs_fhandle_t));
538 if (!tlm_cat_path(fdip->fd_dir_name, dir, nm)) {
539 free(fdip);
540 syslog(LOG_DEBUG, "TAPE BACKUP Find> path too long [%s][%s]",
541 dir, nm);
542 return (NULL);
543 }
544 return (fdip);
545 }
546
547 /*
548 * sysattr_rdonly
549 *
550 * Check if the attribute file is one of the readonly system
551 * attributes.
552 */
553 int
554 sysattr_rdonly(char *name)
555 {
556 return (name && strcmp(name, SYSATTR_RDONLY) == 0);
557 }
558
559 /*
560 * sysattr_rw
|