server: Fix command line parsing when there are multiple parameters.
[nbdkit/ericb.git] / src / utils.c
blob9a039b2a23534d22b25188586e6b409717bb478b
1 /* nbdkit
2 * Copyright (C) 2013 Red Hat Inc.
3 * All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are
7 * met:
9 * * Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
12 * * Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
16 * * Neither the name of Red Hat nor the names of its contributors may be
17 * used to endorse or promote products derived from this software without
18 * specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY RED HAT AND CONTRIBUTORS ''AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
22 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
23 * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL RED HAT OR
24 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
27 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
28 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
29 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
30 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31 * SUCH DAMAGE.
34 #include <config.h>
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <stdbool.h>
39 #include <stdint.h>
40 #include <inttypes.h>
41 #include <string.h>
42 #include <unistd.h>
43 #include <errno.h>
45 #include "nbdkit-plugin.h"
46 #include "internal.h"
48 char *
49 nbdkit_absolute_path (const char *path)
51 CLEANUP_FREE char *pwd = NULL;
52 char *ret;
54 if (path == NULL || *path == '\0') {
55 nbdkit_error ("cannot convert null or empty path to an absolute path");
56 return NULL;
59 if (*path == '/') {
60 ret = strdup (path);
61 if (!ret) {
62 nbdkit_error ("strdup: %m");
63 return NULL;
65 return ret;
68 pwd = get_current_dir_name ();
69 if (pwd == NULL) {
70 nbdkit_error ("get_current_dir_name: %m");
71 return NULL;
74 if (asprintf (&ret, "%s/%s", pwd, path) == -1) {
75 nbdkit_error ("asprintf: %m");
76 return NULL;
79 return ret;
82 /* XXX Multiple problems with this function. Really we should use the
83 * 'human*' functions from gnulib.
85 int64_t
86 nbdkit_parse_size (const char *str)
88 uint64_t size;
89 char t;
91 if (sscanf (str, "%" SCNu64, &size) == 1)
92 return (int64_t) size;
93 if (sscanf (str, "%" SCNu64 "%c", &size, &t) == 2) {
94 switch (t) {
95 case 'b': case 'B':
96 return (int64_t) size;
97 case 'k': case 'K':
98 return (int64_t) size * 1024;
99 case 'm': case 'M':
100 return (int64_t) size * 1024 * 1024;
101 case 'g': case 'G':
102 return (int64_t) size * 1024 * 1024 * 1024;
103 case 't': case 'T':
104 return (int64_t) size * 1024 * 1024 * 1024 * 1024;
105 case 'p': case 'P':
106 return (int64_t) size * 1024 * 1024 * 1024 * 1024 * 1024;
107 case 'e': case 'E':
108 return (int64_t) size * 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
110 case 's': case 'S': /* "sectors", ie. units of 512 bytes,
111 * even if that's not the real sector size
113 return (int64_t) size * 512;
115 default:
116 nbdkit_error ("could not parse size: unknown specifier '%c'", t);
117 return -1;
121 nbdkit_error ("could not parse size string (%s)", str);
122 return -1;
125 /* Write buffer to socket and either succeed completely (returns 0)
126 * or fail (returns -1).
129 xwrite (int sock, const void *vbuf, size_t len)
131 const char *buf = vbuf;
132 ssize_t r;
134 while (len > 0) {
135 r = write (sock, buf, len);
136 if (r == -1) {
137 if (errno == EINTR || errno == EAGAIN)
138 continue;
139 return -1;
141 buf += r;
142 len -= r;
145 return 0;
148 /* Read buffer from socket and either succeed completely (returns > 0),
149 * read an EOF (returns 0), or fail (returns -1).
152 xread (int sock, void *vbuf, size_t len)
154 char *buf = vbuf;
155 ssize_t r;
156 bool first_read = true;
158 while (len > 0) {
159 r = read (sock, buf, len);
160 if (r == -1) {
161 if (errno == EINTR || errno == EAGAIN)
162 continue;
163 return -1;
165 if (r == 0) {
166 if (first_read)
167 return 0;
168 /* Partial record read. This is an error. */
169 errno = EBADMSG;
170 return -1;
172 first_read = false;
173 buf += r;
174 len -= r;
177 return 1;