]> git.sesse.net Git - bcachefs-tools-debian/blob - util.c
finish ripping out libnih
[bcachefs-tools-debian] / util.c
1 #include <alloca.h>
2 #include <ctype.h>
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <limits.h>
6 #include <linux/fs.h>
7 #include <math.h>
8 #include <stdbool.h>
9 #include <stdlib.h>
10 #include <string.h>
11 #include <sys/ioctl.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15
16 #include <uuid/uuid.h>
17
18 #include "ccan/crc/crc.h"
19
20 #include "util.h"
21
22 /* Integer stuff: */
23
24 u64 rounddown_pow_of_two(u64 n)
25 {
26         u64 ret;
27
28         do {
29                 ret = n;
30                 n &= n - 1;
31         } while (n);
32
33         return ret;
34 }
35
36 unsigned ilog2(u64 n)
37 {
38         unsigned ret = 0;
39
40         while (n) {
41                 ret++;
42                 n >>= 1;
43         }
44
45         return ret;
46 }
47
48 char *skip_spaces(const char *str)
49 {
50         while (isspace(*str))
51                 ++str;
52         return (char *)str;
53 }
54
55 char *strim(char *s)
56 {
57         size_t size;
58         char *end;
59
60         s = skip_spaces(s);
61         size = strlen(s);
62         if (!size)
63                 return s;
64
65         end = s + size - 1;
66         while (end >= s && isspace(*end))
67                 end--;
68         *(end + 1) = '\0';
69
70         return s;
71 }
72
73 struct units_buf pr_units(u64 v, enum units units)
74 {
75         struct units_buf ret;
76
77         switch (units) {
78         case BYTES:
79                 snprintf(ret.b, sizeof(ret.b), "%llu", v << 9);
80                 break;
81         case SECTORS:
82                 snprintf(ret.b, sizeof(ret.b), "%llu", v);
83                 break;
84         case HUMAN_READABLE:
85                 v <<= 9;
86
87                 if (v >= 1024) {
88                         int exp = log(v) / log(1024);
89                         snprintf(ret.b, sizeof(ret.b), "%.1f%c",
90                                  v / pow(1024, exp),
91                                  "KMGTPE"[exp-1]);
92                 } else {
93                         snprintf(ret.b, sizeof(ret.b), "%llu", v);
94                 }
95
96                 break;
97         }
98
99         return ret;
100 }
101
102 /* Argument parsing stuff: */
103
104 long strtoul_or_die(const char *p, size_t max, const char *msg)
105 {
106         errno = 0;
107         long v = strtol(p, NULL, 10);
108         if (errno || v < 0 || v >= max)
109                 die("Invalid %s %zi", msg, v);
110
111         return v;
112 }
113
114 u64 hatoi(const char *s)
115 {
116         char *e;
117         long long i = strtoll(s, &e, 10);
118         switch (*e) {
119                 case 't':
120                 case 'T':
121                         i *= 1024;
122                 case 'g':
123                 case 'G':
124                         i *= 1024;
125                 case 'm':
126                 case 'M':
127                         i *= 1024;
128                 case 'k':
129                 case 'K':
130                         i *= 1024;
131         }
132         return i;
133 }
134
135 unsigned hatoi_validate(const char *s, const char *msg)
136 {
137         u64 v = hatoi(s);
138
139         if (v & (v - 1))
140                 die("%s must be a power of two", msg);
141
142         v /= 512;
143
144         if (v > USHRT_MAX)
145                 die("%s too large\n", msg);
146
147         if (!v)
148                 die("%s too small\n", msg);
149
150         return v;
151 }
152
153 unsigned nr_args(char * const *args)
154 {
155         unsigned i;
156
157         for (i = 0; args[i]; i++)
158                 ;
159
160         return i;
161 }
162
163 /* File parsing (i.e. sysfs) */
164
165 char *read_file_str(int dirfd, const char *path)
166 {
167         int fd = openat(dirfd, path, O_RDONLY);
168
169         if (fd < 0)
170                 die("Unable to open %s\n", path);
171
172         struct stat statbuf;
173         if (fstat(fd, &statbuf) < 0)
174                 die("fstat error\n");
175
176         char *buf = malloc(statbuf.st_size + 1);
177
178         int len = read(fd, buf, statbuf.st_size);
179         if (len < 0)
180                 die("read error while reading from file %s\n", path);
181
182         buf[len] = '\0';
183         if (len && buf[len - 1] == '\n')
184                 buf[len - 1] = '\0';
185
186         close(fd);
187
188         return buf;
189 }
190
191 u64 read_file_u64(int dirfd, const char *path)
192 {
193         char *buf = read_file_str(dirfd, path);
194         u64 ret = strtoll(buf, NULL, 10);
195
196         free(buf);
197         return ret;
198 }
199
200 /* String list options: */
201
202 ssize_t read_string_list(const char *buf, const char * const list[])
203 {
204         size_t i;
205         char *s, *d = strdup(buf);
206         if (!d)
207                 return -ENOMEM;
208
209         s = strim(d);
210
211         for (i = 0; list[i]; i++)
212                 if (!strcmp(list[i], s))
213                         break;
214
215         free(d);
216
217         if (!list[i])
218                 return -EINVAL;
219
220         return i;
221 }
222
223 ssize_t read_string_list_or_die(const char *opt, const char * const list[],
224                                 const char *msg)
225 {
226         ssize_t v = read_string_list(opt, list);
227         if (v < 0)
228                 die("Bad %s %s", msg, opt);
229
230         return v;
231 }
232
233 void print_string_list(const char * const list[], size_t selected)
234 {
235         size_t i;
236
237         for (i = 0; list[i]; i++) {
238                 if (i)
239                         putchar(' ');
240                 printf(i == selected ? "[%s] ": "%s", list[i]);
241         }
242 }
243
244 /* Returns size of file or block device, in units of 512 byte sectors: */
245 u64 get_size(const char *path, int fd)
246 {
247         struct stat statbuf;
248         if (fstat(fd, &statbuf))
249                 die("Error statting %s: %s", path, strerror(errno));
250
251         if (!S_ISBLK(statbuf.st_mode))
252                 return statbuf.st_size >> 9;
253
254         u64 ret;
255         if (ioctl(fd, BLKGETSIZE64, &ret))
256                 die("Error getting block device size on %s: %s\n",
257                     path, strerror(errno));
258
259         return ret >> 9;
260 }
261
262 /* Returns blocksize in units of 512 byte sectors: */
263 unsigned get_blocksize(const char *path, int fd)
264 {
265         struct stat statbuf;
266         if (fstat(fd, &statbuf))
267                 die("Error statting %s: %s", path, strerror(errno));
268
269         if (!S_ISBLK(statbuf.st_mode))
270                 return statbuf.st_blksize >> 9;
271
272         unsigned ret;
273         if (ioctl(fd, BLKPBSZGET, &ret))
274                 die("Error getting blocksize on %s: %s\n",
275                     path, strerror(errno));
276
277         return ret >> 9;
278 }
279
280 /* Checksums: */
281
282 /*
283  * Portions Copyright (c) 1996-2001, PostgreSQL Global Development Group (Any
284  * use permitted, subject to terms of PostgreSQL license; see.)
285
286  * If we have a 64-bit integer type, then a 64-bit CRC looks just like the
287  * usual sort of implementation. (See Ross Williams' excellent introduction
288  * A PAINLESS GUIDE TO CRC ERROR DETECTION ALGORITHMS, available from
289  * ftp://ftp.rocksoft.com/papers/crc_v3.txt or several other net sites.)
290  * If we have no working 64-bit type, then fake it with two 32-bit registers.
291  *
292  * The present implementation is a normal (not "reflected", in Williams'
293  * terms) 64-bit CRC, using initial all-ones register contents and a final
294  * bit inversion. The chosen polynomial is borrowed from the DLT1 spec
295  * (ECMA-182, available from http://www.ecma.ch/ecma1/STAND/ECMA-182.HTM):
296  *
297  * x^64 + x^62 + x^57 + x^55 + x^54 + x^53 + x^52 + x^47 + x^46 + x^45 +
298  * x^40 + x^39 + x^38 + x^37 + x^35 + x^33 + x^32 + x^31 + x^29 + x^27 +
299  * x^24 + x^23 + x^22 + x^21 + x^19 + x^17 + x^13 + x^12 + x^10 + x^9 +
300  * x^7 + x^4 + x + 1
301 */
302
303 static const u64 crc_table[256] = {
304         0x0000000000000000ULL, 0x42F0E1EBA9EA3693ULL, 0x85E1C3D753D46D26ULL,
305         0xC711223CFA3E5BB5ULL, 0x493366450E42ECDFULL, 0x0BC387AEA7A8DA4CULL,
306         0xCCD2A5925D9681F9ULL, 0x8E224479F47CB76AULL, 0x9266CC8A1C85D9BEULL,
307         0xD0962D61B56FEF2DULL, 0x17870F5D4F51B498ULL, 0x5577EEB6E6BB820BULL,
308         0xDB55AACF12C73561ULL, 0x99A54B24BB2D03F2ULL, 0x5EB4691841135847ULL,
309         0x1C4488F3E8F96ED4ULL, 0x663D78FF90E185EFULL, 0x24CD9914390BB37CULL,
310         0xE3DCBB28C335E8C9ULL, 0xA12C5AC36ADFDE5AULL, 0x2F0E1EBA9EA36930ULL,
311         0x6DFEFF5137495FA3ULL, 0xAAEFDD6DCD770416ULL, 0xE81F3C86649D3285ULL,
312         0xF45BB4758C645C51ULL, 0xB6AB559E258E6AC2ULL, 0x71BA77A2DFB03177ULL,
313         0x334A9649765A07E4ULL, 0xBD68D2308226B08EULL, 0xFF9833DB2BCC861DULL,
314         0x388911E7D1F2DDA8ULL, 0x7A79F00C7818EB3BULL, 0xCC7AF1FF21C30BDEULL,
315         0x8E8A101488293D4DULL, 0x499B3228721766F8ULL, 0x0B6BD3C3DBFD506BULL,
316         0x854997BA2F81E701ULL, 0xC7B97651866BD192ULL, 0x00A8546D7C558A27ULL,
317         0x4258B586D5BFBCB4ULL, 0x5E1C3D753D46D260ULL, 0x1CECDC9E94ACE4F3ULL,
318         0xDBFDFEA26E92BF46ULL, 0x990D1F49C77889D5ULL, 0x172F5B3033043EBFULL,
319         0x55DFBADB9AEE082CULL, 0x92CE98E760D05399ULL, 0xD03E790CC93A650AULL,
320         0xAA478900B1228E31ULL, 0xE8B768EB18C8B8A2ULL, 0x2FA64AD7E2F6E317ULL,
321         0x6D56AB3C4B1CD584ULL, 0xE374EF45BF6062EEULL, 0xA1840EAE168A547DULL,
322         0x66952C92ECB40FC8ULL, 0x2465CD79455E395BULL, 0x3821458AADA7578FULL,
323         0x7AD1A461044D611CULL, 0xBDC0865DFE733AA9ULL, 0xFF3067B657990C3AULL,
324         0x711223CFA3E5BB50ULL, 0x33E2C2240A0F8DC3ULL, 0xF4F3E018F031D676ULL,
325         0xB60301F359DBE0E5ULL, 0xDA050215EA6C212FULL, 0x98F5E3FE438617BCULL,
326         0x5FE4C1C2B9B84C09ULL, 0x1D14202910527A9AULL, 0x93366450E42ECDF0ULL,
327         0xD1C685BB4DC4FB63ULL, 0x16D7A787B7FAA0D6ULL, 0x5427466C1E109645ULL,
328         0x4863CE9FF6E9F891ULL, 0x0A932F745F03CE02ULL, 0xCD820D48A53D95B7ULL,
329         0x8F72ECA30CD7A324ULL, 0x0150A8DAF8AB144EULL, 0x43A04931514122DDULL,
330         0x84B16B0DAB7F7968ULL, 0xC6418AE602954FFBULL, 0xBC387AEA7A8DA4C0ULL,
331         0xFEC89B01D3679253ULL, 0x39D9B93D2959C9E6ULL, 0x7B2958D680B3FF75ULL,
332         0xF50B1CAF74CF481FULL, 0xB7FBFD44DD257E8CULL, 0x70EADF78271B2539ULL,
333         0x321A3E938EF113AAULL, 0x2E5EB66066087D7EULL, 0x6CAE578BCFE24BEDULL,
334         0xABBF75B735DC1058ULL, 0xE94F945C9C3626CBULL, 0x676DD025684A91A1ULL,
335         0x259D31CEC1A0A732ULL, 0xE28C13F23B9EFC87ULL, 0xA07CF2199274CA14ULL,
336         0x167FF3EACBAF2AF1ULL, 0x548F120162451C62ULL, 0x939E303D987B47D7ULL,
337         0xD16ED1D631917144ULL, 0x5F4C95AFC5EDC62EULL, 0x1DBC74446C07F0BDULL,
338         0xDAAD56789639AB08ULL, 0x985DB7933FD39D9BULL, 0x84193F60D72AF34FULL,
339         0xC6E9DE8B7EC0C5DCULL, 0x01F8FCB784FE9E69ULL, 0x43081D5C2D14A8FAULL,
340         0xCD2A5925D9681F90ULL, 0x8FDAB8CE70822903ULL, 0x48CB9AF28ABC72B6ULL,
341         0x0A3B7B1923564425ULL, 0x70428B155B4EAF1EULL, 0x32B26AFEF2A4998DULL,
342         0xF5A348C2089AC238ULL, 0xB753A929A170F4ABULL, 0x3971ED50550C43C1ULL,
343         0x7B810CBBFCE67552ULL, 0xBC902E8706D82EE7ULL, 0xFE60CF6CAF321874ULL,
344         0xE224479F47CB76A0ULL, 0xA0D4A674EE214033ULL, 0x67C58448141F1B86ULL,
345         0x253565A3BDF52D15ULL, 0xAB1721DA49899A7FULL, 0xE9E7C031E063ACECULL,
346         0x2EF6E20D1A5DF759ULL, 0x6C0603E6B3B7C1CAULL, 0xF6FAE5C07D3274CDULL,
347         0xB40A042BD4D8425EULL, 0x731B26172EE619EBULL, 0x31EBC7FC870C2F78ULL,
348         0xBFC9838573709812ULL, 0xFD39626EDA9AAE81ULL, 0x3A28405220A4F534ULL,
349         0x78D8A1B9894EC3A7ULL, 0x649C294A61B7AD73ULL, 0x266CC8A1C85D9BE0ULL,
350         0xE17DEA9D3263C055ULL, 0xA38D0B769B89F6C6ULL, 0x2DAF4F0F6FF541ACULL,
351         0x6F5FAEE4C61F773FULL, 0xA84E8CD83C212C8AULL, 0xEABE6D3395CB1A19ULL,
352         0x90C79D3FEDD3F122ULL, 0xD2377CD44439C7B1ULL, 0x15265EE8BE079C04ULL,
353         0x57D6BF0317EDAA97ULL, 0xD9F4FB7AE3911DFDULL, 0x9B041A914A7B2B6EULL,
354         0x5C1538ADB04570DBULL, 0x1EE5D94619AF4648ULL, 0x02A151B5F156289CULL,
355         0x4051B05E58BC1E0FULL, 0x87409262A28245BAULL, 0xC5B073890B687329ULL,
356         0x4B9237F0FF14C443ULL, 0x0962D61B56FEF2D0ULL, 0xCE73F427ACC0A965ULL,
357         0x8C8315CC052A9FF6ULL, 0x3A80143F5CF17F13ULL, 0x7870F5D4F51B4980ULL,
358         0xBF61D7E80F251235ULL, 0xFD913603A6CF24A6ULL, 0x73B3727A52B393CCULL,
359         0x31439391FB59A55FULL, 0xF652B1AD0167FEEAULL, 0xB4A25046A88DC879ULL,
360         0xA8E6D8B54074A6ADULL, 0xEA16395EE99E903EULL, 0x2D071B6213A0CB8BULL,
361         0x6FF7FA89BA4AFD18ULL, 0xE1D5BEF04E364A72ULL, 0xA3255F1BE7DC7CE1ULL,
362         0x64347D271DE22754ULL, 0x26C49CCCB40811C7ULL, 0x5CBD6CC0CC10FAFCULL,
363         0x1E4D8D2B65FACC6FULL, 0xD95CAF179FC497DAULL, 0x9BAC4EFC362EA149ULL,
364         0x158E0A85C2521623ULL, 0x577EEB6E6BB820B0ULL, 0x906FC95291867B05ULL,
365         0xD29F28B9386C4D96ULL, 0xCEDBA04AD0952342ULL, 0x8C2B41A1797F15D1ULL,
366         0x4B3A639D83414E64ULL, 0x09CA82762AAB78F7ULL, 0x87E8C60FDED7CF9DULL,
367         0xC51827E4773DF90EULL, 0x020905D88D03A2BBULL, 0x40F9E43324E99428ULL,
368         0x2CFFE7D5975E55E2ULL, 0x6E0F063E3EB46371ULL, 0xA91E2402C48A38C4ULL,
369         0xEBEEC5E96D600E57ULL, 0x65CC8190991CB93DULL, 0x273C607B30F68FAEULL,
370         0xE02D4247CAC8D41BULL, 0xA2DDA3AC6322E288ULL, 0xBE992B5F8BDB8C5CULL,
371         0xFC69CAB42231BACFULL, 0x3B78E888D80FE17AULL, 0x7988096371E5D7E9ULL,
372         0xF7AA4D1A85996083ULL, 0xB55AACF12C735610ULL, 0x724B8ECDD64D0DA5ULL,
373         0x30BB6F267FA73B36ULL, 0x4AC29F2A07BFD00DULL, 0x08327EC1AE55E69EULL,
374         0xCF235CFD546BBD2BULL, 0x8DD3BD16FD818BB8ULL, 0x03F1F96F09FD3CD2ULL,
375         0x41011884A0170A41ULL, 0x86103AB85A2951F4ULL, 0xC4E0DB53F3C36767ULL,
376         0xD8A453A01B3A09B3ULL, 0x9A54B24BB2D03F20ULL, 0x5D45907748EE6495ULL,
377         0x1FB5719CE1045206ULL, 0x919735E51578E56CULL, 0xD367D40EBC92D3FFULL,
378         0x1476F63246AC884AULL, 0x568617D9EF46BED9ULL, 0xE085162AB69D5E3CULL,
379         0xA275F7C11F7768AFULL, 0x6564D5FDE549331AULL, 0x279434164CA30589ULL,
380         0xA9B6706FB8DFB2E3ULL, 0xEB46918411358470ULL, 0x2C57B3B8EB0BDFC5ULL,
381         0x6EA7525342E1E956ULL, 0x72E3DAA0AA188782ULL, 0x30133B4B03F2B111ULL,
382         0xF7021977F9CCEAA4ULL, 0xB5F2F89C5026DC37ULL, 0x3BD0BCE5A45A6B5DULL,
383         0x79205D0E0DB05DCEULL, 0xBE317F32F78E067BULL, 0xFCC19ED95E6430E8ULL,
384         0x86B86ED5267CDBD3ULL, 0xC4488F3E8F96ED40ULL, 0x0359AD0275A8B6F5ULL,
385         0x41A94CE9DC428066ULL, 0xCF8B0890283E370CULL, 0x8D7BE97B81D4019FULL,
386         0x4A6ACB477BEA5A2AULL, 0x089A2AACD2006CB9ULL, 0x14DEA25F3AF9026DULL,
387         0x562E43B4931334FEULL, 0x913F6188692D6F4BULL, 0xD3CF8063C0C759D8ULL,
388         0x5DEDC41A34BBEEB2ULL, 0x1F1D25F19D51D821ULL, 0xD80C07CD676F8394ULL,
389         0x9AFCE626CE85B507ULL
390 };
391
392 static u64 bch_crc64_update(u64 crc, const void *_data, size_t len)
393 {
394         const unsigned char *data = _data;
395
396         while (len--) {
397                 int i = ((int) (crc >> 56) ^ *data++) & 0xFF;
398                 crc = crc_table[i] ^ (crc << 8);
399         }
400
401         return crc;
402 }
403
404 static u64 bch_checksum_update(unsigned type, u64 crc, const void *data, size_t len)
405 {
406         switch (type) {
407         case BCH_CSUM_NONE:
408                 return 0;
409         case BCH_CSUM_CRC32C:
410                 return crc32c(crc, data, len);
411         case BCH_CSUM_CRC64:
412                 return bch_crc64_update(crc, data, len);
413         default:
414                 die("Unknown checksum type %u", type);
415         }
416 }
417
418 u64 bch_checksum(unsigned type, const void *data, size_t len)
419 {
420         u64 crc = 0xffffffffffffffffULL;
421
422         crc = bch_checksum_update(type, crc, data, len);
423
424         return crc ^ 0xffffffffffffffffULL;
425 }
426
427 /* Global control device: */
428 int bcachectl_open(void)
429 {
430         int fd = open("/dev/bcache-ctl", O_RDWR);
431         if (fd < 0)
432                 die("Can't open bcache device: %s", strerror(errno));
433
434         return fd;
435 }
436
437 /* Filesystem handles (ioctl, sysfs dir): */
438
439 #define SYSFS_BASE "/sys/fs/bcache/"
440
441 struct bcache_handle bcache_fs_open(const char *path)
442 {
443         struct bcache_handle ret;
444         uuid_t tmp;
445
446         if (!uuid_parse(path, tmp)) {
447                 /* It's a UUID, look it up in sysfs: */
448
449                 char *sysfs = alloca(strlen(SYSFS_BASE) + strlen(path) + 1);
450                 sprintf(sysfs, "%s%s", SYSFS_BASE, path);
451
452                 ret.sysfs = opendir(sysfs);
453                 if (!ret.sysfs)
454                         die("Unable to open %s\n", path);
455
456                 char *minor = read_file_str(dirfd(ret.sysfs), "minor");
457                 char *ctl = alloca(20 + strlen(minor));
458
459                 sprintf(ctl, "/dev/bcache%s-ctl", minor);
460                 free(minor);
461
462                 ret.fd = open(ctl, O_RDWR);
463                 if (ret.fd < 0)
464                         die("Error opening control device: %s\n",
465                             strerror(errno));
466         } else {
467                 /* It's a path: */
468
469                 ret.fd = open(path, O_RDONLY);
470                 if (ret.fd < 0)
471                         die("Error opening %s: %s\n",
472                             path, strerror(errno));
473
474                 struct bch_ioctl_query_uuid uuid;
475                 if (ioctl(ret.fd, BCH_IOCTL_QUERY_UUID, &uuid))
476                         die("ioctl error (not a bcache fs?): %s\n",
477                             strerror(errno));
478
479                 char uuid_str[40];
480                 uuid_unparse(uuid.uuid.b, uuid_str);
481
482                 char *sysfs = alloca(strlen(SYSFS_BASE) + strlen(uuid_str) + 1);
483                 sprintf(sysfs, "%s%s", SYSFS_BASE, uuid_str);
484
485                 ret.sysfs = opendir(sysfs);
486                 if (!ret.sysfs)
487                         die("Unable to open sysfs dir %s: %s\n",
488                             sysfs, strerror(errno));
489         }
490
491         return ret;
492 }
493
494 bool ask_proceed(void)
495 {
496         const char *short_yes = "yY";
497         char *buf = NULL;
498         size_t buflen = 0;
499         bool ret;
500
501         fputs("Proceed anyway? (y,n) ", stdout);
502
503         if (getline(&buf, &buflen, stdin) < 0)
504                 die("error reading from standard input");
505
506         ret = strchr(short_yes, buf[0]);
507         free(buf);
508         return ret;
509 }
510
511 void memzero_explicit(void *buf, size_t len)
512 {
513     void *(* volatile memset_s)(void *s, int c, size_t n) = memset;
514     memset_s(buf, 0, len);
515 }