Home | History | Annotate | Download | only in oslib
      1 /*
      2  * Copyright (c) Artem Bityutskiy, 2007, 2008
      3  *
      4  * This program is free software; you can redistribute it and/or modify
      5  * it under the terms of the GNU General Public License as published by
      6  * the Free Software Foundation; either version 2 of the License, or
      7  * (at your option) any later version.
      8  *
      9  * This program is distributed in the hope that it will be useful,
     10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See
     12  * the GNU General Public License for more details.
     13  *
     14  * You should have received a copy of the GNU General Public License
     15  * along with this program; if not, write to the Free Software
     16  * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
     17  */
     18 
     19 /* Imported from mtd-utils by dehrenberg */
     20 
     21 #ifndef __MTD_UTILS_COMMON_H__
     22 #define __MTD_UTILS_COMMON_H__
     23 
     24 #include <stdbool.h>
     25 #include <stdio.h>
     26 #include <stdlib.h>
     27 #include <ctype.h>
     28 #include <string.h>
     29 #include <fcntl.h>
     30 #include <errno.h>
     31 #include <features.h>
     32 #include <inttypes.h>
     33 #include <sys/sysmacros.h>
     34 
     35 #ifndef PROGRAM_NAME
     36 # error "You must define PROGRAM_NAME before including this header"
     37 #endif
     38 
     39 #ifdef __cplusplus
     40 extern "C" {
     41 #endif
     42 
     43 #ifndef MIN	/* some C lib headers define this for us */
     44 #define MIN(a, b) ((a) < (b) ? (a) : (b))
     45 #endif
     46 #ifndef MAX
     47 #define MAX(a, b) ((a) > (b) ? (a) : (b))
     48 #endif
     49 #define min(a, b) MIN(a, b) /* glue for linux kernel source */
     50 #define ARRAY_SIZE(a) (sizeof(a) / sizeof((a)[0]))
     51 
     52 #define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1)
     53 #define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask))
     54 
     55 #define min_t(t,x,y) ({ \
     56 	typeof((x)) _x = (x); \
     57 	typeof((y)) _y = (y); \
     58 	(_x < _y) ? _x : _y; \
     59 })
     60 
     61 #define max_t(t,x,y) ({ \
     62 	typeof((x)) _x = (x); \
     63 	typeof((y)) _y = (y); \
     64 	(_x > _y) ? _x : _y; \
     65 })
     66 
     67 #ifndef O_CLOEXEC
     68 #define O_CLOEXEC 0
     69 #endif
     70 
     71 /* define a print format specifier for off_t */
     72 #ifdef __USE_FILE_OFFSET64
     73 #define PRIxoff_t PRIx64
     74 #define PRIdoff_t PRId64
     75 #else
     76 #define PRIxoff_t "l"PRIx32
     77 #define PRIdoff_t "l"PRId32
     78 #endif
     79 
     80 /* Verbose messages */
     81 #define bareverbose(verbose, fmt, ...) do {                        \
     82 	if (verbose)                                               \
     83 		printf(fmt, ##__VA_ARGS__);                        \
     84 } while(0)
     85 #define verbose(verbose, fmt, ...) \
     86 	bareverbose(verbose, "%s: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__)
     87 
     88 /* Normal messages */
     89 #define normsg_cont(fmt, ...) do {                                 \
     90 	printf("%s: " fmt, PROGRAM_NAME, ##__VA_ARGS__);           \
     91 } while(0)
     92 #define normsg(fmt, ...) do {                                      \
     93 	normsg_cont(fmt "\n", ##__VA_ARGS__);                      \
     94 } while(0)
     95 
     96 /* Error messages */
     97 #define errmsg(fmt, ...)  ({                                                \
     98 	fprintf(stderr, "%s: error!: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__); \
     99 	-1;                                                                 \
    100 })
    101 #define errmsg_die(fmt, ...) do {                                           \
    102 	exit(errmsg(fmt, ##__VA_ARGS__));                                   \
    103 } while(0)
    104 
    105 /* System error messages */
    106 #define sys_errmsg(fmt, ...)  ({                                            \
    107 	int _err = errno;                                                   \
    108 	errmsg(fmt, ##__VA_ARGS__);                                         \
    109 	fprintf(stderr, "%*serror %d (%s)\n", (int)sizeof(PROGRAM_NAME) + 1,\
    110 		"", _err, strerror(_err));                                  \
    111 	-1;                                                                 \
    112 })
    113 #define sys_errmsg_die(fmt, ...) do {                                       \
    114 	exit(sys_errmsg(fmt, ##__VA_ARGS__));                               \
    115 } while(0)
    116 
    117 /* Warnings */
    118 #define warnmsg(fmt, ...) do {                                                \
    119 	fprintf(stderr, "%s: warning!: " fmt "\n", PROGRAM_NAME, ##__VA_ARGS__); \
    120 } while(0)
    121 
    122 #if defined(__UCLIBC__)
    123 /* uClibc versions before 0.9.34 don't have rpmatch() */
    124 #if __UCLIBC_MAJOR__ == 0 && \
    125 		(__UCLIBC_MINOR__ < 9 || \
    126 		(__UCLIBC_MINOR__ == 9 && __UCLIBC_SUBLEVEL__ < 34))
    127 #undef rpmatch
    128 #define rpmatch __rpmatch
    129 static inline int __rpmatch(const char *resp)
    130 {
    131     return (resp[0] == 'y' || resp[0] == 'Y') ? 1 :
    132 	(resp[0] == 'n' || resp[0] == 'N') ? 0 : -1;
    133 }
    134 #endif
    135 #endif
    136 
    137 /**
    138  * prompt the user for confirmation
    139  */
    140 static inline bool prompt(const char *msg, bool def)
    141 {
    142 	char *line = NULL;
    143 	size_t len;
    144 	bool ret = def;
    145 
    146 	do {
    147 		normsg_cont("%s (%c/%c) ", msg, def ? 'Y' : 'y', def ? 'n' : 'N');
    148 		fflush(stdout);
    149 
    150 		while (getline(&line, &len, stdin) == -1) {
    151 			printf("failed to read prompt; assuming '%s'\n",
    152 				def ? "yes" : "no");
    153 			break;
    154 		}
    155 
    156 		if (strcmp("\n", line) != 0) {
    157 			switch (rpmatch(line)) {
    158 			case 0: ret = false; break;
    159 			case 1: ret = true; break;
    160 			case -1:
    161 				puts("unknown response; please try again");
    162 				continue;
    163 			}
    164 		}
    165 		break;
    166 	} while (1);
    167 
    168 	free(line);
    169 
    170 	return ret;
    171 }
    172 
    173 static inline int is_power_of_2(unsigned long long n)
    174 {
    175 	return (n != 0 && ((n & (n - 1)) == 0));
    176 }
    177 
    178 /**
    179  * simple_strtoX - convert a hex/dec/oct string into a number
    180  * @snum: buffer to convert
    181  * @error: set to 1 when buffer isn't fully consumed
    182  *
    183  * These functions are similar to the standard strtoX() functions, but they are
    184  * a little bit easier to use if you want to convert full string of digits into
    185  * the binary form. The typical usage:
    186  *
    187  * int error = 0;
    188  * unsigned long num;
    189  *
    190  * num = simple_strtoul(str, &error);
    191  * if (error || ... if needed, your check that num is not out of range ...)
    192  * 	error_happened();
    193  */
    194 #define simple_strtoX(func, type) \
    195 static inline type simple_##func(const char *snum, int *error) \
    196 { \
    197 	char *endptr; \
    198 	type ret = func(snum, &endptr, 0); \
    199  \
    200 	if (error && (!*snum || *endptr)) { \
    201 		errmsg("%s: unable to parse the number '%s'", #func, snum); \
    202 		*error = 1; \
    203 	} \
    204  \
    205 	return ret; \
    206 }
    207 simple_strtoX(strtol, long int)
    208 simple_strtoX(strtoll, long long int)
    209 simple_strtoX(strtoul, unsigned long int)
    210 simple_strtoX(strtoull, unsigned long long int)
    211 
    212 /* Simple version-printing for utils */
    213 #define common_print_version() \
    214 do { \
    215 	printf("%s %s\n", PROGRAM_NAME, VERSION); \
    216 } while (0)
    217 
    218 #include "libmtd_xalloc.h"
    219 
    220 #ifdef __cplusplus
    221 }
    222 #endif
    223 
    224 #endif /* !__MTD_UTILS_COMMON_H__ */
    225