memcp: fix #83
[awesomized/libmemcached] / clients / memcp.cc
index 59bd7478bb780a89d447d9c8949b1381c7342baa..d87e0cad0cb4bc1486ab60b9ef23a9f9b4f1bdc8 100644 (file)
@@ -1,4 +1,5 @@
 /* LibMemcached
+ * Copyright (C) 2011-2013 Data Differential, http://datadifferential.com/
  * Copyright (C) 2006-2009 Brian Aker
  * All rights reserved.
  *
@@ -9,7 +10,7 @@
  *
  */
 
-#include "config.h"
+#include "mem_config.h"
 
 #include <cerrno>
 #include <climits>
@@ -30,7 +31,7 @@
 #include <unistd.h>
 
 
-#include <libmemcached/memcached.h>
+#include <libmemcached-1.0/memcached.h>
 
 #include "client_options.h"
 #include "utilities.h"
@@ -67,13 +68,13 @@ static long strtol_wrapper(const char *nptr, int base, bool *error)
       or (errno != 0 && val == 0))
   {
     *error= true;
-    return EXIT_SUCCESS;
+    return 0;
   }
 
   if (endptr == nptr)
   {
     *error= true;
-    return EXIT_SUCCESS;
+    return 0;
   }
 
   *error= false;
@@ -84,6 +85,13 @@ int main(int argc, char *argv[])
 {
 
   options_parse(argc, argv);
+
+  if (optind >= argc)
+  {
+    fprintf(stderr, "Expected argument after options\n");
+    exit(EXIT_FAILURE);
+  }
+
   initialize_sockets();
 
   memcached_st *memc= memcached_create(NULL);
@@ -128,21 +136,25 @@ int main(int argc, char *argv[])
     {
       opt_servers= strdup(temp);
     }
-    else
+#if 0
+    else if (argc >= 1 and argv[--argc])
+    {
+      opt_servers= strdup(argv[argc]);
+    }
+#endif
+
+    if (opt_servers == NULL)
     {
       std::cerr << "No Servers provided" << std::endl;
       exit(EXIT_FAILURE);
     }
   }
 
-  memcached_server_st *servers;
-  if (opt_servers)
-  {
-    servers= memcached_servers_parse(opt_servers);
-  }
-  else
+  memcached_server_st* servers= memcached_servers_parse(opt_servers);
+  if (servers == NULL or memcached_server_list_count(servers) == 0)
   {
-    servers= memcached_servers_parse(argv[--argc]);
+    std::cerr << "Invalid server list provided:" << opt_servers << std::endl;
+    return EXIT_FAILURE;
   }
 
   memcached_server_push(memc, servers);
@@ -172,17 +184,20 @@ int main(int argc, char *argv[])
     int fd= open(argv[optind], O_RDONLY);
     if (fd < 0)
     {
-      if (opt_verbose)
-      {
-        std::cerr << "memcp " << argv[optind] << " " << strerror(errno) << std::endl;
-        optind++;
-      }
+      std::cerr << "memcp " << argv[optind] << " " << strerror(errno) << std::endl;
+      optind++;
       exit_code= EXIT_FAILURE;
       continue;
     }
 
     struct stat sbuf;
-    (void)fstat(fd, &sbuf);
+    if (fstat(fd, &sbuf) == -1)
+    {
+      std::cerr << "memcp " << argv[optind] << " " << strerror(errno) << std::endl;
+      optind++;
+      exit_code= EXIT_FAILURE;
+      continue;
+    }
 
     char *ptr= rindex(argv[optind], '/');
     if (ptr)
@@ -203,24 +218,33 @@ int main(int argc, char *argv[])
             ptr, opt_flags, (unsigned long)opt_expires);
     }
 
-    char *file_buffer_ptr;
-    if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
+    // The file may be empty
+    char *file_buffer_ptr= NULL;
+    if (sbuf.st_size > 0)
     {
-      std::cerr << "Error allocating file buffer(" << strerror(errno) << ")" << std::endl;
-      exit(EXIT_FAILURE);
-    }
+      if ((file_buffer_ptr= (char *)malloc(sizeof(char) * (size_t)sbuf.st_size)) == NULL)
+      {
+        std::cerr << "Error allocating file buffer(" << strerror(errno) << ")" << std::endl;
+        close(fd);
+        exit(EXIT_FAILURE);
+      }
 
-    ssize_t read_length;
-    if ((read_length= ::read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
-    {
-      std::cerr << "Error while reading file " << file_buffer_ptr << " (" << strerror(errno) << ")" << std::endl;
-      exit(EXIT_FAILURE);
-    }
+      ssize_t read_length;
+      if ((read_length= ::read(fd, file_buffer_ptr, (size_t)sbuf.st_size)) == -1)
+      {
+        std::cerr << "Error while reading file " << file_buffer_ptr << " (" << strerror(errno) << ")" << std::endl;
+        close(fd);
+        free(file_buffer_ptr);
+        exit(EXIT_FAILURE);
+      }
 
-    if (read_length != sbuf.st_size)
-    {
-      std::cerr << "Failure while reading file. Read length was not equal to stat() length" << std::endl;
-      exit(EXIT_FAILURE);
+      if (read_length != sbuf.st_size)
+      {
+        std::cerr << "Failure while reading file. Read length was not equal to stat() length" << std::endl;
+        close(fd);
+        free(file_buffer_ptr);
+        exit(EXIT_FAILURE);
+      }
     }
 
     memcached_return_t rc;
@@ -358,10 +382,10 @@ static void options_parse(int argc, char *argv[])
     case OPT_EXPIRE: /* --expire */
       {
         bool strtol_error;
-        opt_expires= (time_t)strtol_wrapper(optarg, 16, &strtol_error);
+        opt_expires= (time_t)strtol_wrapper(optarg, 10, &strtol_error);
         if (strtol_error == true)
         {
-          fprintf(stderr, "Bad value passed via --flag\n");
+          fprintf(stderr, "Bad value passed via --expire\n");
           exit(1);
         }
       }