1 /*-
2 * Copyright (c) 2014-2018 MongoDB, Inc.
3 * Copyright (c) 2008-2014 WiredTiger, Inc.
4 * All rights reserved.
5 *
6 * See the file LICENSE for redistribution information.
7 */
8
9 #include "util.h"
10
11 int
util_cerr(WT_CURSOR * cursor,const char * op,int ret)12 util_cerr(WT_CURSOR *cursor, const char *op, int ret)
13 {
14 return (
15 util_err(cursor->session, ret, "%s: cursor.%s", cursor->uri, op));
16 }
17
18 /*
19 * util_err --
20 * Report an error.
21 */
22 int
util_err(WT_SESSION * session,int e,const char * fmt,...)23 util_err(WT_SESSION *session, int e, const char *fmt, ...)
24 {
25 va_list ap;
26
27 (void)fprintf(stderr, "%s: ", progname);
28 if (fmt != NULL) {
29 va_start(ap, fmt);
30 (void)vfprintf(stderr, fmt, ap);
31 va_end(ap);
32 if (e != 0)
33 (void)fprintf(stderr, ": ");
34 }
35 if (e != 0)
36 (void)fprintf(stderr, "%s", session == NULL ?
37 wiredtiger_strerror(e) : session->strerror(session, e));
38 (void)fprintf(stderr, "\n");
39 return (1);
40 }
41
42 /*
43 * util_read_line --
44 * Read a line from stdin into a ULINE.
45 */
46 int
util_read_line(WT_SESSION * session,ULINE * l,bool eof_expected,bool * eofp)47 util_read_line(WT_SESSION *session, ULINE *l, bool eof_expected, bool *eofp)
48 {
49 static uint64_t line = 0;
50 size_t len;
51 int ch;
52
53 ++line;
54 *eofp = false;
55
56 if (l->memsize == 0) {
57 if ((l->mem = realloc(l->mem, l->memsize + 1024)) == NULL)
58 return (util_err(session, errno, NULL));
59 l->memsize = 1024;
60 }
61 for (len = 0;; ++len) {
62 if ((ch = getchar()) == EOF) {
63 if (len == 0) {
64 if (eof_expected) {
65 *eofp = true;
66 return (0);
67 }
68 return (util_err(session, 0,
69 "line %" PRIu64 ": unexpected end-of-file",
70 line));
71 }
72 return (util_err(session, 0,
73 "line %" PRIu64 ": no newline terminator", line));
74 }
75 if (ch == '\n')
76 break;
77 /*
78 * We nul-terminate the string so it's easier to convert the
79 * line into a record number, that means we always need one
80 * extra byte at the end.
81 */
82 if (len >= l->memsize - 1) {
83 if ((l->mem =
84 realloc(l->mem, l->memsize + 1024)) == NULL)
85 return (util_err(session, errno, NULL));
86 l->memsize += 1024;
87 }
88 ((uint8_t *)l->mem)[len] = (uint8_t)ch;
89 }
90
91 ((uint8_t *)l->mem)[len] = '\0'; /* nul-terminate */
92
93 return (0);
94 }
95
96 /*
97 * util_str2num --
98 * Convert a string to a number.
99 */
100 int
util_str2num(WT_SESSION * session,const char * p,bool endnul,uint64_t * vp)101 util_str2num(WT_SESSION *session, const char *p, bool endnul, uint64_t *vp)
102 {
103 uint64_t v;
104 char *endptr;
105
106 /*
107 * strtouq takes lots of things like hex values, signs and so on and so
108 * forth -- none of them are OK with us. Check the string starts with
109 * digit, that turns off the special processing.
110 */
111 if (!__wt_isdigit((u_char)p[0]))
112 goto format;
113
114 errno = 0;
115 v = __wt_strtouq(p, &endptr, 0);
116 if (v == ULLONG_MAX && errno == ERANGE)
117 return (util_err(session, ERANGE, "%s: invalid number", p));
118
119 /*
120 * In most cases we expect the number to be a string and end with a
121 * nul byte (and we want to confirm that because it's a user-entered
122 * command-line argument), but we allow the caller to configure that
123 * test off.
124 */
125 if (endnul && endptr[0] != '\0')
126 format: return (util_err(session, EINVAL, "%s: invalid number", p));
127
128 *vp = v;
129 return (0);
130 }
131
132 /*
133 * util_flush --
134 * Flush the file successfully, or drop it.
135 */
136 int
util_flush(WT_SESSION * session,const char * uri)137 util_flush(WT_SESSION *session, const char *uri)
138 {
139 WT_DECL_RET;
140 size_t len;
141 char *buf;
142
143 len = strlen(uri) + 100;
144 if ((buf = malloc(len)) == NULL)
145 return (util_err(session, errno, NULL));
146
147 if ((ret = __wt_snprintf(buf, len, "target=(\"%s\")", uri)) != 0) {
148 free(buf);
149 return (util_err(session, ret, NULL));
150 }
151 ret = session->checkpoint(session, buf);
152 free(buf);
153
154 if (ret == 0)
155 return (0);
156
157 (void)util_err(session, ret, "%s: session.checkpoint", uri);
158 if ((ret = session->drop(session, uri, NULL)) != 0)
159 (void)util_err(session, ret, "%s: session.drop", uri);
160 return (1);
161 }
162