8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / cmd / ndmpd / tlm / tlm_util.c
blobd2215e9cdc2cedf6040a131319981dddc4135673
1 /*
2 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
3 * Use is subject to license terms.
4 * Copyright 2012 Milan Jurik. All rights reserved.
5 */
7 /*
8 * BSD 3 Clause License
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
14 * are met:
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
21 * distribution.
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.
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.
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"
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.
58 * cstack_new
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.
64 cstack_t *
65 cstack_new(void)
67 cstack_t *stk;
69 if ((stk = ndmp_malloc(sizeof (cstack_t))) == NULL)
70 return (NULL);
72 return (stk);
77 * cstack_delete
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.
83 void
84 cstack_delete(cstack_t *stk)
86 cstack_t *tmp;
88 if (stk == NULL) {
89 NDMP_LOG(LOG_DEBUG, "cstack_delete: invalid stack");
90 return;
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);
99 NDMP_LOG(LOG_DEBUG, "cstack_delete: 0x%p", stk);
100 free(stk);
105 * cstack_push
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)
117 cstack_t *stk_node;
119 if (stk == NULL) {
120 NDMP_LOG(LOG_DEBUG, "cstack_push: invalid stack");
121 return (-1);
124 if ((stk_node = ndmp_malloc(sizeof (cstack_t))) == NULL)
125 return (-1);
127 stk_node->data = data;
128 stk_node->len = len;
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);
133 return (0);
138 * cstack_pop
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)
148 cstack_t *stk_node;
150 if (stk == NULL) {
151 NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
152 return (-1);
155 if ((stk_node = stk->next) == NULL) {
156 NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
157 return (-1);
160 if (data)
161 *data = stk_node->data;
163 if (len)
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);
169 free(stk_node);
170 return (0);
174 * cstack_top
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)
183 if (stk == NULL) {
184 NDMP_LOG(LOG_DEBUG, "cstack_pop: invalid stack");
185 return (-1);
188 if (stk->next == NULL) {
189 NDMP_LOG(LOG_DEBUG, "cstack_pop: underflow");
190 return (-1);
193 if (data)
194 *data = stk->next->data;
196 if (len)
197 *len = stk->next->len;
199 return (0);
203 * match
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
210 * AB String 'A' followed by string 'B'
211 * * Any String, including the empty string
213 boolean_t
214 match(char *patn, char *str)
216 for (; ; ) {
217 switch (*patn) {
218 case 0:
219 return (*str == 0);
221 case '?':
222 if (*str != 0) {
223 str++;
224 patn++;
225 continue;
227 return (FALSE);
229 case '*':
230 patn++;
231 if (*patn == 0)
232 return (TRUE);
234 while (*str) {
235 if (match(patn, str))
236 return (TRUE);
237 str++;
239 return (FALSE);
241 default:
242 if (*str != *patn)
243 return (FALSE);
244 str++;
245 patn++;
246 continue;
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))
263 return (TRUE);
264 if (strchr(str, '.') == 0)
265 return (TRUE);
266 return (FALSE);
268 for (; ; ) {
269 switch (*patn) {
270 case 0:
271 return (*str == 0);
273 case '?':
274 if (*str != 0) {
275 str++;
276 patn++;
277 continue;
279 return (FALSE);
281 case '*':
282 patn++;
283 if (*patn == 0)
284 return (TRUE);
286 while (*str) {
287 if (match_ci(patn, str))
288 return (TRUE);
289 str++;
291 return (FALSE);
293 default:
294 if (*str != *patn) {
295 int c1 = *str;
296 int c2 = *patn;
298 c1 = tolower(c1);
299 c2 = tolower(c2);
300 if (c1 != c2)
301 return (FALSE);
303 str++;
304 patn++;
305 continue;
308 /* NOT REACHED */
312 * Linear matching against a list utility function
314 static boolean_t
315 parse_match(char line, char *seps)
317 char *sep = seps;
319 while (*sep != 0) {
320 /* compare this char with the seperator list */
321 if (*sep == line)
322 return (TRUE);
323 sep++;
325 return (FALSE);
329 * Returns the next entry of the list after
330 * each separator
332 char *
333 parse(char **line, char *seps)
335 char *start = *line;
337 while (**line != 0) {
338 *line = *line + 1;
339 if (parse_match(**line, seps)) {
340 /* hit a terminator, skip trailing terminators */
341 while (parse_match(**line, seps)) {
342 **line = 0;
343 *line = *line + 1;
345 break;
348 return (start);
352 * oct_atoi
354 * Convert an octal string to integer
357 oct_atoi(char *p)
359 int v = 0;
360 int c;
362 while (*p == ' ')
363 p++;
365 while ('0' <= (c = *p++) && c <= '7') {
366 v <<= 3;
367 v += c - '0';
370 return (v);
374 * strupr
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.
381 char *
382 strupr(char *s)
384 char c;
385 unsigned char *p = (unsigned char *)s;
387 while (*p) {
388 c = toupper(*p);
389 *p++ = c;
391 return (s);
395 * trim_whitespace
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
401 * returned.
403 char *
404 trim_whitespace(char *buf)
406 char *p = buf;
407 char *q = buf;
409 if (buf == 0)
410 return (0);
412 while (*p && isspace(*p))
413 ++p;
415 while ((*q = *p++) != 0)
416 ++q;
418 if (q != buf) {
419 while ((--q, isspace(*q)) != 0)
420 *q = '\0';
423 return (buf);
427 * trim_name
429 * Trims the slash and dot slash from the beginning of the
430 * path name.
432 char *
433 trim_name(char *nm)
435 while (*nm) {
436 if (*nm == '/') {
437 nm++;
438 continue;
440 if (*nm == '.' && nm[1] == '/' && nm[2]) {
441 nm += 2;
442 continue;
444 break;
446 return (nm);
450 * get_volname
452 * Extract the volume name from the path
454 char *
455 get_volname(char *path)
457 char *cp, *save;
458 int sp;
460 if (!path)
461 return (NULL);
463 if (!(save = strdup(path)))
464 return (NULL);
466 sp = strspn(path, "/");
467 if (*(path + sp) == '\0') {
468 free(save);
469 return (NULL);
472 if ((cp = strchr(save + sp, '/')))
473 *cp = '\0';
475 return (save);
479 * fs_volexist
481 * Check if the volume exists
483 boolean_t
484 fs_volexist(char *path)
486 struct stat64 st;
487 char *p;
489 if ((p = get_volname(path)) == NULL)
490 return (FALSE);
492 if (stat64(p, &st) != 0) {
493 free(p);
494 return (FALSE);
497 free(p);
498 return (TRUE);
502 * tlm_tarhdr_size
504 * Returns the size of the TLM_TAR_HDR structure.
507 tlm_tarhdr_size(void)
509 return (sizeof (tlm_tar_hdr_t));
513 * dup_dir_info
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));
523 if (new_dir_info) {
524 bcopy(old_dir_info, new_dir_info,
525 sizeof (struct full_dir_info));
527 return (new_dir_info);
531 * tlm_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))))
542 return (NULL);
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);
551 return (fdip);
555 * sysattr_rdonly
557 * Check if the attribute file is one of the readonly system
558 * attributes.
561 sysattr_rdonly(char *name)
563 return (name && strcmp(name, SYSATTR_RDONLY) == 0);
567 * sysattr_rw
569 * Check if the attribute file is one of the read/write system
570 * attributes.
573 sysattr_rw(char *name)
575 return (name && strcmp(name, SYSATTR_RW) == 0);