Imported Upstream version 7.59.0
[platform/upstream/curl.git] / lib / smb.c
index acf31bc..b432634 100644 (file)
--- a/lib/smb.c
+++ b/lib/smb.c
@@ -6,7 +6,7 @@
  *                             \___|\___/|_| \_\_____|
  *
  * Copyright (C) 2014, Bill Nagel <wnagel@tycoint.com>, Exacq Technologies
- * Copyright (C) 2016-2017, Daniel Stenberg, <daniel@haxx.se>, et al.
+ * Copyright (C) 2016-2018, Daniel Stenberg, <daniel@haxx.se>, et al.
  *
  * This software is licensed as described in the file COPYING, which
  * you should have received as part of this distribution. The terms
@@ -34,7 +34,7 @@
 #include <process.h>
 #ifdef CURL_WINDOWS_APP
 #define getpid GetCurrentProcessId
-#else
+#elif !defined(MSDOS)
 #define getpid _getpid
 #endif
 #endif
@@ -85,6 +85,7 @@ const struct Curl_handler Curl_handler_smb = {
   ZERO_NULL,                            /* perform_getsock */
   smb_disconnect,                       /* disconnect */
   ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* connection_check */
   PORT_SMB,                             /* defport */
   CURLPROTO_SMB,                        /* protocol */
   PROTOPT_NONE                          /* flags */
@@ -109,6 +110,7 @@ const struct Curl_handler Curl_handler_smbs = {
   ZERO_NULL,                            /* perform_getsock */
   smb_disconnect,                       /* disconnect */
   ZERO_NULL,                            /* readwrite */
+  ZERO_NULL,                            /* connection_check */
   PORT_SMBS,                            /* defport */
   CURLPROTO_SMBS,                       /* protocol */
   PROTOPT_SSL                           /* flags */
@@ -144,19 +146,12 @@ static unsigned int smb_swap32(unsigned int x)
     ((x >> 24) & 0xff);
 }
 
-#ifdef HAVE_LONGLONG
-static unsigned long long smb_swap64(unsigned long long x)
+static curl_off_t smb_swap64(curl_off_t x)
 {
-  return ((unsigned long long) smb_swap32((unsigned int) x) << 32) |
+  return ((curl_off_t) smb_swap32((unsigned int) x) << 32) |
     smb_swap32((unsigned int) (x >> 32));
 }
-#else
-static unsigned __int64 smb_swap64(unsigned __int64 x)
-{
-  return ((unsigned __int64) smb_swap32((unsigned int) x) << 32) |
-    smb_swap32((unsigned int) (x >> 32));
-}
-#endif
+
 #else
 #  define smb_swap16(x) (x)
 #  define smb_swap32(x) (x)
@@ -446,7 +441,7 @@ static CURLcode smb_send_setup(struct connectdata *conn)
 
   Curl_ntlm_core_mk_lm_hash(conn->data, conn->passwd, lm_hash);
   Curl_ntlm_core_lm_resp(lm_hash, smbc->challenge, lm);
-#if USE_NTRESPONSES
+#ifdef USE_NTRESPONSES
   Curl_ntlm_core_mk_nt_hash(conn->data, conn->passwd, nt_hash);
   Curl_ntlm_core_lm_resp(nt_hash, smbc->challenge, nt);
 #else
@@ -607,7 +602,7 @@ static CURLcode smb_send_and_recv(struct connectdata *conn, void **msg)
 
   /* Check if there is data in the transfer buffer */
   if(!smbc->send_size && smbc->upload_size) {
-    int nread = smbc->upload_size > BUFSIZE ? BUFSIZE :
+    int nread = smbc->upload_size > UPLOAD_BUFSIZE ? UPLOAD_BUFSIZE :
       (int) smbc->upload_size;
     conn->data->req.upload_fromhere = conn->data->state.uploadbuffer;
     result = Curl_fillreadbuffer(conn, nread, &nread);
@@ -646,7 +641,7 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
   if(smbc->state == SMB_CONNECTING) {
 #ifdef USE_SSL
     if((conn->handler->flags & PROTOPT_SSL)) {
-      bool ssl_done;
+      bool ssl_done = FALSE;
       result = Curl_ssl_connect_nonblocking(conn, FIRSTSOCKET, &ssl_done);
       if(result && result != CURLE_AGAIN)
         return result;
@@ -713,6 +708,24 @@ static CURLcode smb_connection_state(struct connectdata *conn, bool *done)
   return CURLE_OK;
 }
 
+/*
+ * Convert a timestamp from the Windows world (100 nsec units from 1 Jan 1601)
+ * to Posix time. Cap the output to fit within a time_t.
+ */
+static void get_posix_time(time_t *out, curl_off_t timestamp)
+{
+  timestamp -= 116444736000000000;
+  timestamp /= 10000000;
+#if SIZEOF_TIME_T < SIZEOF_CURL_OFF_T
+  if(timestamp > TIME_T_MAX)
+    *out = TIME_T_MAX;
+  else if(timestamp < TIME_T_MIN)
+    *out = TIME_T_MIN;
+  else
+#endif
+    *out = (time_t) timestamp;
+}
+
 static CURLcode smb_request_state(struct connectdata *conn, bool *done)
 {
   struct smb_request *req = conn->data->req.protop;
@@ -723,6 +736,7 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
   unsigned short off;
   CURLcode result;
   void *msg = NULL;
+  const struct smb_nt_create_response *smb_m;
 
   /* Start the request */
   if(req->state == SMB_REQUESTING) {
@@ -765,7 +779,8 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
       next_state = SMB_TREE_DISCONNECT;
       break;
     }
-    req->fid = smb_swap16(((struct smb_nt_create_response *)msg)->fid);
+    smb_m = (const struct smb_nt_create_response*) msg;
+    req->fid = smb_swap16(smb_m->fid);
     conn->data->req.offset = 0;
     if(conn->data->set.upload) {
       conn->data->req.size = conn->data->state.infilesize;
@@ -773,9 +788,11 @@ static CURLcode smb_request_state(struct connectdata *conn, bool *done)
       next_state = SMB_UPLOAD;
     }
     else {
-      conn->data->req.size =
-        smb_swap64(((struct smb_nt_create_response *)msg)->end_of_file);
+      smb_m = (const struct smb_nt_create_response*) msg;
+      conn->data->req.size = smb_swap64(smb_m->end_of_file);
       Curl_pgrsSetDownloadSize(conn->data, conn->data->req.size);
+      if(conn->data->set.get_filetime)
+        get_posix_time(&conn->data->info.filetime, smb_m->last_change_time);
       next_state = SMB_DOWNLOAD;
     }
     break;