char *buffer;
char *s;
+ if (error == 0) {
+ /*
+ * strerror(0) varies among platforms:
+ *
+ * Success
+ * No error
+ * Undefined error: 0
+ *
+ * We want to provide a consistent result here because
+ * our testsuite has test cases which strictly matches
+ * log messages containing this string.
+ */
+ return "Success";
+ }
+
save_errno = errno;
buffer = strerror_buffer_get()->s;
* vSwitch. Otherwise, it is assumed to be an external program linking against
* the Open vSwitch libraries.
*
- * The 'date' and 'time' arguments should likely be called with
- * "__DATE__" and "__TIME__" to use the time the binary was built.
- * Alternatively, the "ovs_set_program_name" macro may be called to do this
- * automatically.
*/
void
-ovs_set_program_name__(const char *argv0, const char *version, const char *date,
- const char *time)
+ovs_set_program_name(const char *argv0, const char *version)
{
char *basename;
#ifdef _WIN32
free(program_version);
if (!strcmp(version, VERSION)) {
- program_version = xasprintf("%s (Open vSwitch) "VERSION"\n"
- "Compiled %s %s\n",
- program_name, date, time);
+ program_version = xasprintf("%s (Open vSwitch) "VERSION"\n",
+ program_name);
} else {
program_version = xasprintf("%s %s\n"
- "Open vSwitch Library "VERSION"\n"
- "Compiled %s %s\n",
- program_name, version, date, time);
+ "Open vSwitch Library "VERSION"\n",
+ program_name, version);
}
}
return name ? name : "";
}
-/* Sets the formatted value of 'format' as the name of the currently running
- * thread or process. (This appears in log messages and may also be visible in
- * system process listings and debuggers.) */
+/* Sets 'subprogram_name' as the name of the currently running thread or
+ * process. (This appears in log messages and may also be visible in system
+ * process listings and debuggers.) */
void
-set_subprogram_name(const char *format, ...)
+set_subprogram_name(const char *subprogram_name)
{
- char *pname;
-
- if (format) {
- va_list args;
-
- va_start(args, format);
- pname = xvasprintf(format, args);
- va_end(args);
- } else {
- pname = xstrdup(program_name);
- }
-
+ char *pname = xstrdup(subprogram_name ? subprogram_name : program_name);
free(subprogram_name_set(pname));
#if HAVE_GLIBC_PTHREAD_SETNAME_NP
return true;
}
-/* Scans the bits in 'p' that have bit offsets 'start' through 'end'
- * (inclusive) for the first bit with value 'target'. If one is found, returns
- * its offset, otherwise 'end'. 'p' is 'len' bytes long.
+/* Scans the bits in 'p' that have bit offsets 'start' (inclusive) through
+ * 'end' (exclusive) for the first bit with value 'target'. If one is found,
+ * returns its offset, otherwise 'end'. 'p' is 'len' bytes long.
*
* If you consider all of 'p' to be a single unsigned integer in network byte
* order, then bit N is the bit with value 2**N. That is, bit 0 is the bit
* start <= end
*/
unsigned int
-bitwise_scan(const void *p_, unsigned int len, bool target, unsigned int start,
+bitwise_scan(const void *p, unsigned int len, bool target, unsigned int start,
unsigned int end)
{
- const uint8_t *p = p_;
unsigned int ofs;
for (ofs = start; ofs < end; ofs++) {
- bool bit = (p[len - (ofs / 8 + 1)] & (1u << (ofs % 8))) != 0;
- if (bit == target) {
+ if (bitwise_get_bit(p, len, ofs) == target) {
break;
}
}
return ofs;
}
+/* Scans the bits in 'p' that have bit offsets 'start' (inclusive) through
+ * 'end' (exclusive) for the first bit with value 'target', in reverse order.
+ * If one is found, returns its offset, otherwise 'end'. 'p' is 'len' bytes
+ * long.
+ *
+ * If you consider all of 'p' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N. That is, bit 0 is the bit
+ * with value 1 in p[len - 1], bit 1 is the bit with value 2, bit 2 is the bit
+ * with value 4, ..., bit 8 is the bit with value 1 in p[len - 2], and so on.
+ *
+ * To scan an entire bit array in reverse order, specify start == len * 8 - 1
+ * and end == -1, in which case the return value is nonnegative if successful
+ * and -1 if no 'target' match is found.
+ *
+ * Required invariant:
+ * start >= end
+ */
+int
+bitwise_rscan(const void *p, unsigned int len, bool target, int start, int end)
+{
+ const uint8_t *s = p;
+ int start_byte = len - (start / 8 + 1);
+ int end_byte = len - (end / 8 + 1);
+ int ofs_byte;
+ int ofs;
+ uint8_t the_byte;
+
+ /* Find the target in the start_byte from starting offset */
+ ofs_byte = start_byte;
+ the_byte = s[ofs_byte];
+ for (ofs = start % 8; ofs >= 0; ofs--) {
+ if (((the_byte & (1u << ofs)) != 0) == target) {
+ break;
+ }
+ }
+ if (ofs < 0) {
+ /* Target not found in start byte, continue searching byte by byte */
+ for (ofs_byte = start_byte + 1; ofs_byte <= end_byte; ofs_byte++) {
+ if ((target && s[ofs_byte])
+ || (!target && (s[ofs_byte] != 0xff))) {
+ break;
+ }
+ }
+ if (ofs_byte > end_byte) {
+ return end;
+ }
+ the_byte = s[ofs_byte];
+ /* Target is in the_byte, find it bit by bit */
+ for (ofs = 7; ofs >= 0; ofs--) {
+ if (((the_byte & (1u << ofs)) != 0) == target) {
+ break;
+ }
+ }
+ }
+ int ret = (len - ofs_byte) * 8 - (8 - ofs);
+ if (ret < end) {
+ return end;
+ }
+ return ret;
+}
/* Copies the 'n_bits' low-order bits of 'value' into the 'n_bits' bits
* starting at bit 'dst_ofs' in 'dst', which is 'dst_len' bytes long.
n_bits);
return ntohll(value);
}
+
+/* Returns the value of the bit with offset 'ofs' in 'src', which is 'len'
+ * bytes long.
+ *
+ * If you consider all of 'src' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N. That is, bit 0 is the bit
+ * with value 1 in src[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in src[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ * ofs < len * 8
+ */
+bool
+bitwise_get_bit(const void *src_, unsigned int len, unsigned int ofs)
+{
+ const uint8_t *src = src_;
+
+ return (src[len - (ofs / 8 + 1)] & (1u << (ofs % 8))) != 0;
+}
+
+/* Sets the bit with offset 'ofs' in 'dst', which is 'len' bytes long, to 0.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N. That is, bit 0 is the bit
+ * with value 1 in dst[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in dst[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ * ofs < len * 8
+ */
+void
+bitwise_put0(void *dst_, unsigned int len, unsigned int ofs)
+{
+ uint8_t *dst = dst_;
+
+ dst[len - (ofs / 8 + 1)] &= ~(1u << (ofs % 8));
+}
+
+/* Sets the bit with offset 'ofs' in 'dst', which is 'len' bytes long, to 1.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N. That is, bit 0 is the bit
+ * with value 1 in dst[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in dst[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ * ofs < len * 8
+ */
+void
+bitwise_put1(void *dst_, unsigned int len, unsigned int ofs)
+{
+ uint8_t *dst = dst_;
+
+ dst[len - (ofs / 8 + 1)] |= 1u << (ofs % 8);
+}
+
+/* Sets the bit with offset 'ofs' in 'dst', which is 'len' bytes long, to 'b'.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N. That is, bit 0 is the bit
+ * with value 1 in dst[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in dst[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ * ofs < len * 8
+ */
+void
+bitwise_put_bit(void *dst, unsigned int len, unsigned int ofs, bool b)
+{
+ if (b) {
+ bitwise_put1(dst, len, ofs);
+ } else {
+ bitwise_put0(dst, len, ofs);
+ }
+}
+
+/* Flips the bit with offset 'ofs' in 'dst', which is 'len' bytes long.
+ *
+ * If you consider all of 'dst' to be a single unsigned integer in network byte
+ * order, then bit N is the bit with value 2**N. That is, bit 0 is the bit
+ * with value 1 in dst[len - 1], bit 1 is the bit with value 2, bit 2 is the
+ * bit with value 4, ..., bit 8 is the bit with value 1 in dst[len - 2], and so
+ * on.
+ *
+ * Required invariants:
+ * ofs < len * 8
+ */
+void
+bitwise_toggle_bit(void *dst_, unsigned int len, unsigned int ofs)
+{
+ uint8_t *dst = dst_;
+
+ dst[len - (ofs / 8 + 1)] ^= 1u << (ofs % 8);
+}
\f
/* ovs_scan */
ovsrcu_quiesce_end();
}
+/* Determine whether standard output is a tty or not. This is useful to decide
+ * whether to use color output or not when --color option for utilities is set
+ * to `auto`.
+ */
+bool
+is_stdout_a_tty(void)
+{
+ char const *t = getenv("TERM");
+ return (isatty(STDOUT_FILENO) && t && strcmp(t, "dumb") != 0);
+}
+
#ifdef _WIN32
\f
char *
enum { BUFSIZE = sizeof strerror_buffer_get()->s };
char *buffer = strerror_buffer_get()->s;
+ if (error == 0) {
+ /* See ovs_strerror */
+ return "Success";
+ }
+
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, error, 0, buffer, BUFSIZE, NULL);
return buffer;