Fixes a typo/oops that shows up on openbsd.
[m6w6/libmemcached] / clients / memcp.c
1 /* LibMemcached
2 * Copyright (C) 2006-2009 Brian Aker
3 * All rights reserved.
4 *
5 * Use and distribution licensed under the BSD license. See
6 * the COPYING file in the parent directory for full text.
7 *
8 * Summary:
9 *
10 */
11
12 #include "config.h"
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <inttypes.h>
17 #include <unistd.h>
18 #include <getopt.h>
19 #include <sys/types.h>
20 #include <sys/stat.h>
21 #include <sys/types.h>
22 #include <fcntl.h>
23 #include <errno.h>
24 #include <strings.h>
25 #include <string.h>
26 #include <sys/types.h>
27 #include <stdlib.h>
28 #include <limits.h>
29
30
31 #include <libmemcached/memcached.h>
32
33 #include "client_options.h"
34 #include "utilities.h"
35
36 #define PROGRAM_NAME "memcp"
37 #define PROGRAM_DESCRIPTION "Copy a set of files to a memcached cluster."
38
39 /* Prototypes */
40 static void options_parse(int argc, char *argv[]);
41
42 static int opt_binary=0;
43 static int opt_verbose= 0;
44 static char *opt_servers= NULL;
45 static char *opt_hash= NULL;
46 static int opt_method= OPT_SET;
47 static uint32_t opt_flags= 0;
48 static time_t opt_expires= 0;
49 static char *opt_username;
50 static char *opt_passwd;
51
52 static long strtol_wrapper(const char *nptr, int base, bool *error)
53 {
54 long val;
55 char *endptr;
56
57 errno= 0; /* To distinguish success/failure after call */
58 val= strtol(nptr, &endptr, base);
59
60 /* Check for various possible errors */
61
62 if ((errno == ERANGE && (val == LONG_MAX || val == LONG_MIN))
63 || (errno != 0 && val == 0))
64 {
65 *error= true;
66 return 0;
67 }
68
69 if (endptr == nptr)
70 {
71 *error= true;
72 return 0;
73 }
74
75 *error= false;
76 return val;
77 }
78
79 int main(int argc, char *argv[])
80 {
81 memcached_st *memc;
82 memcached_return_t rc;
83 memcached_server_st *servers;
84
85 int return_code= 0;
86
87 options_parse(argc, argv);
88
89 memc= memcached_create(NULL);
90 process_hash_option(memc, opt_hash);
91
92 if (!opt_servers)
93 {
94 char *temp;
95
96 if ((temp= getenv("MEMCACHED_SERVERS")))
97 {
98 opt_servers= strdup(temp);
99 }
100 else
101 {
102 fprintf(stderr, "No Servers provided\n");
103 exit(1);
104 }
105 }
106
107 if (opt_servers)
108 servers= memcached_servers_parse(opt_servers);
109 else
110 servers= memcached_servers_parse(argv[--argc]);
111
112 memcached_server_push(memc, servers);
113 memcached_server_list_free(servers);
114 memcached_behavior_set(memc, MEMCACHED_BEHAVIOR_BINARY_PROTOCOL,
115 (uint64_t)opt_binary);
116 if (!initialize_sasl(memc, opt_username, opt_passwd))
117 {
118 memcached_free(memc);
119 return 1;
120 }
121
122 while (optind < argc)
123 {
124 struct stat sbuf;
125 int fd;
126 char *ptr;
127 ssize_t read_length;
128 char *file_buffer_ptr;
129
130 fd= open(argv[optind], O_RDONLY);
131 if (fd < 0)
132 {
133 fprintf(stderr, "memcp: %s: %s\n", argv[optind], strerror(errno));
134 optind++;
135 continue;
136 }
137
138 (void)fstat(fd, &sbuf);
139
140 ptr= rindex(argv[optind], '/');
141 if (ptr)
142 ptr++;
143 else
144 ptr= argv[optind];
145
146 if (opt_verbose)
147 {
148 static const char *opstr[] = { "set", "add", "replace" };
149 printf("op: %s\nsource file: %s\nlength: %zu\n"
150 "key: %s\nflags: %x\nexpires: %llu\n",
151 opstr[opt_method - OPT_SET], argv[optind], (size_t)sbuf.st_size,
152 ptr, opt_flags, (unsigned long long)opt_expires);
153 }
154
155 if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
156 {
157 fprintf(stderr, "malloc: %s\n", strerror(errno));
158 exit(1);
159 }
160
161 if ((read_length= read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
162 {
163 fprintf(stderr, "read: %s\n", strerror(errno));
164 exit(1);
165 }
166
167 if (read_length != sbuf.st_size)
168 {
169 fprintf(stderr, "Failure reading from file\n");
170 exit(1);
171 }
172
173 if (opt_method == OPT_ADD)
174 rc= memcached_add(memc, ptr, strlen(ptr),
175 file_buffer_ptr, (size_t)sbuf.st_size,
176 opt_expires, opt_flags);
177 else if (opt_method == OPT_REPLACE)
178 rc= memcached_replace(memc, ptr, strlen(ptr),
179 file_buffer_ptr, (size_t)sbuf.st_size,
180 opt_expires, opt_flags);
181 else
182 rc= memcached_set(memc, ptr, strlen(ptr),
183 file_buffer_ptr, (size_t)sbuf.st_size,
184 opt_expires, opt_flags);
185
186 if (rc != MEMCACHED_SUCCESS)
187 {
188 fprintf(stderr, "memcp: %s: memcache error %s",
189 ptr, memcached_strerror(memc, rc));
190 if (memc->cached_errno)
191 fprintf(stderr, " system error %s", strerror(memc->cached_errno));
192 fprintf(stderr, "\n");
193
194 return_code= -1;
195 }
196
197 free(file_buffer_ptr);
198 close(fd);
199 optind++;
200 }
201
202 memcached_free(memc);
203
204 if (opt_servers)
205 free(opt_servers);
206 if (opt_hash)
207 free(opt_hash);
208 shutdown_sasl();
209
210 return return_code;
211 }
212
213 static void options_parse(int argc, char *argv[])
214 {
215 int option_index= 0;
216 int option_rv;
217
218 memcached_programs_help_st help_options[]=
219 {
220 {0},
221 };
222
223 static struct option long_options[]=
224 {
225 {(OPTIONSTRING)"version", no_argument, NULL, OPT_VERSION},
226 {(OPTIONSTRING)"help", no_argument, NULL, OPT_HELP},
227 {(OPTIONSTRING)"verbose", no_argument, &opt_verbose, OPT_VERBOSE},
228 {(OPTIONSTRING)"debug", no_argument, &opt_verbose, OPT_DEBUG},
229 {(OPTIONSTRING)"servers", required_argument, NULL, OPT_SERVERS},
230 {(OPTIONSTRING)"flag", required_argument, NULL, OPT_FLAG},
231 {(OPTIONSTRING)"expire", required_argument, NULL, OPT_EXPIRE},
232 {(OPTIONSTRING)"set", no_argument, NULL, OPT_SET},
233 {(OPTIONSTRING)"add", no_argument, NULL, OPT_ADD},
234 {(OPTIONSTRING)"replace", no_argument, NULL, OPT_REPLACE},
235 {(OPTIONSTRING)"hash", required_argument, NULL, OPT_HASH},
236 {(OPTIONSTRING)"binary", no_argument, NULL, OPT_BINARY},
237 {(OPTIONSTRING)"username", required_argument, NULL, OPT_USERNAME},
238 {(OPTIONSTRING)"password", required_argument, NULL, OPT_PASSWD},
239 {0, 0, 0, 0},
240 };
241
242 while (1)
243 {
244 option_rv= getopt_long(argc, argv, "Vhvds:", long_options, &option_index);
245
246 if (option_rv == -1) break;
247
248 switch (option_rv)
249 {
250 case 0:
251 break;
252 case OPT_BINARY:
253 opt_binary = 1;
254 break;
255 case OPT_VERBOSE: /* --verbose or -v */
256 opt_verbose = OPT_VERBOSE;
257 break;
258 case OPT_DEBUG: /* --debug or -d */
259 opt_verbose = OPT_DEBUG;
260 break;
261 case OPT_VERSION: /* --version or -V */
262 version_command(PROGRAM_NAME);
263 break;
264 case OPT_HELP: /* --help or -h */
265 help_command(PROGRAM_NAME, PROGRAM_DESCRIPTION, long_options, help_options);
266 break;
267 case OPT_SERVERS: /* --servers or -s */
268 opt_servers= strdup(optarg);
269 break;
270 case OPT_FLAG: /* --flag */
271 {
272 bool strtol_error;
273 opt_flags= (uint32_t)strtol_wrapper(optarg, 16, &strtol_error);
274 if (strtol_error == true)
275 {
276 fprintf(stderr, "Bad value passed via --flag\n");
277 exit(1);
278 }
279 break;
280 }
281 case OPT_EXPIRE: /* --expire */
282 {
283 bool strtol_error;
284 opt_expires= (time_t)strtol_wrapper(optarg, 16, &strtol_error);
285 if (strtol_error == true)
286 {
287 fprintf(stderr, "Bad value passed via --flag\n");
288 exit(1);
289 }
290 }
291 case OPT_SET:
292 opt_method= OPT_SET;
293 break;
294 case OPT_REPLACE:
295 opt_method= OPT_REPLACE;
296 break;
297 case OPT_ADD:
298 opt_method= OPT_ADD;
299 break;
300 case OPT_HASH:
301 opt_hash= strdup(optarg);
302 break;
303 case OPT_USERNAME:
304 opt_username= optarg;
305 break;
306 case OPT_PASSWD:
307 opt_passwd= optarg;
308 break;
309 case '?':
310 /* getopt_long already printed an error message. */
311 exit(1);
312 default:
313 abort();
314 }
315 }
316 }