* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
+
#include "qemu/osdep.h"
-#include "qemu-common.h"
#include "qemu/host-utils.h"
#include <math.h>
+#include "qemu-common.h"
#include "qemu/sockets.h"
#include "qemu/iov.h"
#include "net/net.h"
+#include "qemu/ctype.h"
#include "qemu/cutils.h"
#include "qemu/error-report.h"
#endif
}
+/**
+ * Sync changes made to the memory mapped file back to the backing
+ * storage. For POSIX compliant systems this will fallback
+ * to regular msync call. Otherwise it will trigger whole file sync
+ * (including the metadata case there is no support to skip that otherwise)
+ *
+ * @addr - start of the memory area to be synced
+ * @length - length of the are to be synced
+ * @fd - file descriptor for the file to be synced
+ * (mandatory only for POSIX non-compliant systems)
+ */
+int qemu_msync(void *addr, size_t length, int fd)
+{
+#ifdef CONFIG_POSIX
+ size_t align_mask = ~(qemu_real_host_page_size - 1);
+
+ /**
+ * There are no strict reqs as per the length of mapping
+ * to be synced. Still the length needs to follow the address
+ * alignment changes. Additionally - round the size to the multiple
+ * of PAGE_SIZE
+ */
+ length += ((uintptr_t)addr & (qemu_real_host_page_size - 1));
+ length = (length + ~align_mask) & align_mask;
+
+ addr = (void *)((uintptr_t)addr & align_mask);
+
+ return msync(addr, length, MS_SYNC);
+#else /* CONFIG_POSIX */
+ /**
+ * Perform the sync based on the file descriptor
+ * The sync range will most probably be wider than the one
+ * requested - but it will still get the job done
+ */
+ return qemu_fdatasync(fd);
+#endif /* CONFIG_POSIX */
+}
+
#ifndef _WIN32
/* Sets a specific flag */
int fcntl_setfl(int fd, int flag)
/*
* Convert string to bytes, allowing either B/b for bytes, K/k for KB,
* M/m for MB, G/g for GB or T/t for TB. End pointer will be returned
- * in *end, if not NULL. Return -ERANGE on overflow, Return -EINVAL on
+ * in *end, if not NULL. Return -ERANGE on overflow, and -EINVAL on
* other error.
*/
-static int do_strtosz(const char *nptr, char **end,
+static int do_strtosz(const char *nptr, const char **end,
const char default_suffix, int64_t unit,
uint64_t *result)
{
int retval;
- char *endptr;
+ const char *endptr;
unsigned char c;
int mul_required = 0;
double val, mul, integral, fraction;
- errno = 0;
- val = strtod(nptr, &endptr);
- if (isnan(val) || endptr == nptr || errno != 0) {
- retval = -EINVAL;
+ retval = qemu_strtod_finite(nptr, &endptr, &val);
+ if (retval) {
goto out;
}
fraction = modf(val, &integral);
goto out;
}
/*
- * Values >= 0xfffffffffffffc00 overflow uint64_t after their trip
- * through double (53 bits of precision).
+ * Values near UINT64_MAX overflow to 2**64 when converting to double
+ * precision. Compare against the maximum representable double precision
+ * value below 2**64, computed as "the next value after 2**64 (0x1p64) in
+ * the direction of 0".
*/
- if ((val * mul >= 0xfffffffffffffc00) || val < 0) {
+ if ((val * mul > nextafter(0x1p64, 0)) || val < 0) {
retval = -ERANGE;
goto out;
}
return retval;
}
-int qemu_strtosz(const char *nptr, char **end, uint64_t *result)
+int qemu_strtosz(const char *nptr, const char **end, uint64_t *result)
{
return do_strtosz(nptr, end, 'B', 1024, result);
}
-int qemu_strtosz_MiB(const char *nptr, char **end, uint64_t *result)
+int qemu_strtosz_MiB(const char *nptr, const char **end, uint64_t *result)
{
return do_strtosz(nptr, end, 'M', 1024, result);
}
-int qemu_strtosz_metric(const char *nptr, char **end, uint64_t *result)
+int qemu_strtosz_metric(const char *nptr, const char **end, uint64_t *result)
{
return do_strtosz(nptr, end, 'B', 1000, result);
}
* Convert string @nptr to an int64_t.
*
* Works like qemu_strtol(), except it stores INT64_MAX on overflow,
- * and INT_MIN on underflow.
+ * and INT64_MIN on underflow.
*/
int qemu_strtoi64(const char *nptr, const char **endptr, int base,
int64_t *result)
return -EINVAL;
}
+ /* This assumes int64_t is long long TODO relax */
+ QEMU_BUILD_BUG_ON(sizeof(int64_t) != sizeof(long long));
errno = 0;
- /* FIXME This assumes int64_t is long long */
*result = strtoll(nptr, &ep, base);
return check_strtox_error(nptr, ep, endptr, errno);
}
return -EINVAL;
}
+ /* This assumes uint64_t is unsigned long long TODO relax */
+ QEMU_BUILD_BUG_ON(sizeof(uint64_t) != sizeof(unsigned long long));
errno = 0;
- /* FIXME This assumes uint64_t is unsigned long long */
*result = strtoull(nptr, &ep, base);
/* Windows returns 1 for negative out-of-range values. */
if (errno == ERANGE) {
}
/* make sure we reject negative numbers: */
- while (isspace((unsigned char)*s)) {
+ while (qemu_isspace(*s)) {
s++;
}
if (*s == '-') {
{
g_assert(n <= 0x3fff);
if (n < 0x80) {
- *out++ = n;
+ *out = n;
return 1;
} else {
*out++ = (n & 0x7f) | 0x80;
- *out++ = n >> 7;
+ *out = n >> 7;
return 2;
}
}
int uleb128_decode_small(const uint8_t *in, uint32_t *n)
{
if (!(*in & 0x80)) {
- *n = *in++;
+ *n = *in;
return 1;
} else {
*n = *in++ & 0x7f;
if (*in & 0x80) {
return -1;
}
- *n |= *in++ << 7;
+ *n |= *in << 7;
return 2;
}
}
char *size_to_str(uint64_t val)
{
static const char *suffixes[] = { "", "Ki", "Mi", "Gi", "Ti", "Pi", "Ei" };
- unsigned long div;
+ uint64_t div;
int i;
/*