1 : /*
2 : * Copyright (C) 2006-2007 Red Hat, Inc. All rights reserved.
3 : *
4 : * This file is part of the device-mapper userspace tools.
5 : *
6 : * This copyrighted material is made available to anyone wishing to use,
7 : * modify, copy, or redistribute it subject to the terms and conditions
8 : * of the GNU Lesser General Public License v.2.1.
9 : *
10 : * You should have received a copy of the GNU Lesser General Public License
11 : * along with this program; if not, write to the Free Software Foundation,
12 : * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
13 : */
14 :
15 : #include "dmlib.h"
16 : #include "libdevmapper.h"
17 :
18 : #include <ctype.h>
19 :
20 : /*
21 : * consume characters while they match the predicate function.
22 : */
23 72 : static char *_consume(char *buffer, int (*fn) (int))
24 : {
25 336 : while (*buffer && fn(*buffer))
26 192 : buffer++;
27 :
28 72 : return buffer;
29 : }
30 :
31 228 : static int _isword(int c)
32 : {
33 228 : return !isspace(c);
34 : }
35 :
36 : /*
37 : * Split buffer into NULL-separated words in argv.
38 : * Returns number of words.
39 : */
40 9 : int dm_split_words(char *buffer, unsigned max,
41 : unsigned ignore_comments __attribute((unused)),
42 : char **argv)
43 : {
44 : unsigned arg;
45 :
46 45 : for (arg = 0; arg < max; arg++) {
47 36 : buffer = _consume(buffer, isspace);
48 36 : if (!*buffer)
49 0 : break;
50 :
51 36 : argv[arg] = buffer;
52 36 : buffer = _consume(buffer, _isword);
53 :
54 36 : if (*buffer) {
55 36 : *buffer = '\0';
56 36 : buffer++;
57 : }
58 : }
59 :
60 9 : return arg;
61 : }
62 :
63 : /*
64 : * Remove hyphen quoting from a component of a name.
65 : * NULL-terminates the component and returns start of next component.
66 : */
67 0 : static char *_unquote(char *component)
68 : {
69 0 : char *c = component;
70 0 : char *o = c;
71 : char *r;
72 :
73 0 : while (*c) {
74 0 : if (*(c + 1)) {
75 0 : if (*c == '-') {
76 0 : if (*(c + 1) == '-')
77 0 : c++;
78 : else
79 0 : break;
80 : }
81 : }
82 0 : *o = *c;
83 0 : o++;
84 0 : c++;
85 : }
86 :
87 0 : r = (*c) ? c + 1 : c;
88 0 : *o = '\0';
89 :
90 0 : return r;
91 : }
92 :
93 0 : int dm_split_lvm_name(struct dm_pool *mem, const char *dmname,
94 : char **vgname, char **lvname, char **layer)
95 : {
96 0 : if (mem && !(*vgname = dm_pool_strdup(mem, dmname)))
97 0 : return 0;
98 :
99 0 : _unquote(*layer = _unquote(*lvname = _unquote(*vgname)));
100 :
101 0 : return 1;
102 : }
103 :
104 : /*
105 : * On error, up to glibc 2.0.6, snprintf returned -1 if buffer was too small;
106 : * From glibc 2.1 it returns number of chars (excl. trailing null) that would
107 : * have been written had there been room.
108 : *
109 : * dm_snprintf reverts to the old behaviour.
110 : */
111 5416 : int dm_snprintf(char *buf, size_t bufsize, const char *format, ...)
112 : {
113 : int n;
114 : va_list ap;
115 :
116 5416 : va_start(ap, format);
117 5416 : n = vsnprintf(buf, bufsize, format, ap);
118 5416 : va_end(ap);
119 :
120 5416 : if (n < 0 || ((unsigned) n + 1 > bufsize))
121 0 : return -1;
122 :
123 5416 : return n;
124 : }
125 :
126 0 : char *dm_basename(const char *path)
127 : {
128 0 : char *p = strrchr(path, '/');
129 :
130 0 : return p ? p + 1 : (char *) path;
131 : }
132 :
133 0 : int dm_asprintf(char **result, const char *format, ...)
134 : {
135 0 : int n, ok = 0, size = 32;
136 : va_list ap;
137 0 : char *buf = dm_malloc(size);
138 :
139 0 : *result = 0;
140 :
141 0 : if (!buf)
142 0 : return -1;
143 :
144 0 : while (!ok) {
145 0 : va_start(ap, format);
146 0 : n = vsnprintf(buf, size, format, ap);
147 0 : if (0 <= n && n < size)
148 0 : ok = 1;
149 : else {
150 0 : dm_free(buf);
151 0 : size *= 2;
152 0 : buf = dm_malloc(size);
153 0 : if (!buf)
154 0 : return -1;
155 : };
156 0 : va_end(ap);
157 : }
158 :
159 0 : *result = dm_strdup(buf);
160 0 : dm_free(buf);
161 0 : return n + 1;
162 : }
|