Version 1.1.5.
[nbdkit/ericb.git] / src / utils.c
blobffd216aa7ff97a65498bcb37483bb5eb0a972e58
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 "%c", &size, &t) == 2) {
92 switch (t) {
93 case 'b': case 'B':
94 return (int64_t) size;
95 case 'k': case 'K':
96 return (int64_t) size * 1024;
97 case 'm': case 'M':
98 return (int64_t) size * 1024 * 1024;
99 case 'g': case 'G':
100 return (int64_t) size * 1024 * 1024 * 1024;
101 case 't': case 'T':
102 return (int64_t) size * 1024 * 1024 * 1024 * 1024;
103 case 'p': case 'P':
104 return (int64_t) size * 1024 * 1024 * 1024 * 1024 * 1024;
105 case 'e': case 'E':
106 return (int64_t) size * 1024 * 1024 * 1024 * 1024 * 1024 * 1024;
108 case 's': case 'S': /* "sectors", ie. units of 512 bytes,
109 * even if that's not the real sector size
111 return (int64_t) size * 512;
113 default:
114 nbdkit_error ("could not parse size: unknown specifier '%c'", t);
115 return -1;
119 /* bytes */
120 if (sscanf (str, "%" SCNu64, &size) == 1)
121 return (int64_t) size;
123 nbdkit_error ("could not parse size string (%s)", str);
124 return -1;
127 /* Write buffer to socket and either succeed completely (returns 0)
128 * or fail (returns -1).
131 xwrite (int sock, const void *vbuf, size_t len)
133 const char *buf = vbuf;
134 ssize_t r;
136 while (len > 0) {
137 r = write (sock, buf, len);
138 if (r == -1) {
139 if (errno == EINTR || errno == EAGAIN)
140 continue;
141 return -1;
143 buf += r;
144 len -= r;
147 return 0;
150 /* Read buffer from socket and either succeed completely (returns > 0),
151 * read an EOF (returns 0), or fail (returns -1).
154 xread (int sock, void *vbuf, size_t len)
156 char *buf = vbuf;
157 ssize_t r;
158 bool first_read = true;
160 while (len > 0) {
161 r = read (sock, buf, len);
162 if (r == -1) {
163 if (errno == EINTR || errno == EAGAIN)
164 continue;
165 return -1;
167 if (r == 0) {
168 if (first_read)
169 return 0;
170 /* Partial record read. This is an error. */
171 errno = EBADMSG;
172 return -1;
174 first_read = false;
175 buf += r;
176 len -= r;
179 return 1;