check more return codes and skip the initial slash in given file names
authorDaniel Stenberg <daniel@haxx.se>
Mon, 8 May 2006 22:23:33 +0000 (22:23 +0000)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 8 May 2006 22:23:33 +0000 (22:23 +0000)
lib/tftp.c

index 8dacca6..568d12c 100644 (file)
@@ -151,8 +151,8 @@ typedef struct tftp_state_data {
 
 
 /* Forward declarations */
-static void tftp_rx(tftp_state_data_t *state, tftp_event_t event) ;
-static void tftp_tx(tftp_state_data_t *state, tftp_event_t event) ;
+static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event) ;
+static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event) ;
 void tftp_set_timeouts(tftp_state_data_t *state) ;
 
 /**********************************************************
@@ -249,12 +249,16 @@ static unsigned short getrpacketblock(tftp_packet_t *packet)
   return (packet->data[2] << 8) | packet->data[3];
 }
 
-static void tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
+static CURLcode tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
 {
   int sbytes;
   const char *mode = "octet";
-  char *filename = state->conn->path;
+
+  /* As RFC3617 describes the separator slash is not actually part of the file
+     name so we skip the always-present first letter of the path string. */
+  char *filename = &state->conn->path[1];
   struct SessionHandle *data = state->conn->data;
+  CURLcode res;
 
   /* Set ascii mode if -B flag was used */
   if(data->set.ftp_ascii)
@@ -269,7 +273,7 @@ static void tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
     if(state->retries>state->retry_max) {
       state->error = TFTP_ERR_NORESPONSE;
       state->state = TFTP_STATE_FIN;
-      return;
+      return res;
     }
 
     if(data->set.upload) {
@@ -301,15 +305,13 @@ static void tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
     infof(data, "%s\n", "Connected for transmit");
     state->state = TFTP_STATE_TX;
     tftp_set_timeouts(state);
-    tftp_tx(state, event);
-    break;
+    return tftp_tx(state, event);
 
   case TFTP_EVENT_DATA: /* connected for receive */
     infof(data, "%s\n", "Connected for receive");
     state->state = TFTP_STATE_RX;
     tftp_set_timeouts(state);
-    tftp_rx(state, event);
-    break;
+    return tftp_rx(state, event);
 
   case TFTP_EVENT_ERROR:
     state->state = TFTP_STATE_FIN;
@@ -319,6 +321,7 @@ static void tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
     failf(state->conn->data, "tftp_send_first: internal error\n");
     break;
   }
+  return res;
 }
 
 /**********************************************************
@@ -328,7 +331,7 @@ static void tftp_send_first(tftp_state_data_t *state, tftp_event_t event)
  * Event handler for the RX state
  *
  **********************************************************/
-static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
+static CURLcode tftp_rx(tftp_state_data_t *state, tftp_event_t event)
 {
   int sbytes;
   int rblock;
@@ -348,7 +351,7 @@ static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
       if (state->retries>state->retry_max) {
         failf(data, "tftp_rx: giving up waiting for block %d\n",
               state->block+1);
-        return;
+        return CURLE_TFTP_ILLEGAL;
       }
     }
     /* This is the expected block.  Reset counters and ACK it. */
@@ -381,7 +384,8 @@ static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
     if(state->retries > state->retry_max) {
       state->error = TFTP_ERR_TIMEOUT;
       state->state = TFTP_STATE_FIN;
-    } else {
+    }
+    else {
       /* Resend the previous ACK */
       sbytes = sendto(state->sockfd, (void *)&state->spacket,
                       4, SEND_4TH_ARG,
@@ -404,6 +408,7 @@ static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
   }
   Curl_pgrsSetDownloadCounter(data,
                               (curl_off_t) state->block*TFTP_BLOCKSIZE);
+  return CURLE_OK;
 }
 
 /**********************************************************
@@ -413,11 +418,12 @@ static void tftp_rx(tftp_state_data_t *state, tftp_event_t event)
  * Event handler for the TX state
  *
  **********************************************************/
-static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
+static CURLcode tftp_tx(tftp_state_data_t *state, tftp_event_t event)
 {
   struct SessionHandle *data = state->conn->data;
   int sbytes;
   int rblock;
+  CURLcode res = CURLE_OK;
 
   switch(event) {
 
@@ -432,10 +438,11 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
       state->retries++;
       /* Bail out if over the maximum */
       if(state->retries>state->retry_max) {
-        failf(data, "%s\n",
-              "tftp_tx: giving up waiting for block %d ack",
+        failf(data, "tftp_tx: giving up waiting for block %d ack",
               state->block);
-      } else {
+        res = CURLE_SEND_ERROR;
+      }
+      else {
         /* Re-send the data packet */
         sbytes = sendto(state->sockfd, (void *)&state->spacket,
                         4+state->sbytes, SEND_4TH_ARG,
@@ -444,9 +451,10 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
         /* Check all sbytes were sent */
         if(sbytes<0) {
           failf(data, "%s\n", Curl_strerror(state->conn, Curl_sockerrno()));
+          res = CURLE_SEND_ERROR;
         }
       }
-      return;
+      return res;
     }
     /* This is the expected packet.  Reset the counters and send the next
        block */
@@ -456,9 +464,11 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
     setpacketblock(&state->spacket, state->block);
     if(state->block > 1 && state->sbytes < TFTP_BLOCKSIZE) {
       state->state = TFTP_STATE_FIN;
-      return;
+      return CURLE_OK;
     }
-    Curl_fillreadbuffer(state->conn, TFTP_BLOCKSIZE, &state->sbytes);
+    res = Curl_fillreadbuffer(state->conn, TFTP_BLOCKSIZE, &state->sbytes);
+    if(res)
+      return res;
     sbytes = sendto(state->sockfd, (void *)state->spacket.data,
                     4+state->sbytes, SEND_4TH_ARG,
                     (struct sockaddr *)&state->remote_addr,
@@ -502,6 +512,8 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
 
   /* Update the progress meter */
   Curl_pgrsSetUploadCounter(data, (curl_off_t) state->block*TFTP_BLOCKSIZE);
+
+  return res;
 }
 
 /**********************************************************
@@ -514,19 +526,20 @@ static void tftp_tx(tftp_state_data_t *state, tftp_event_t event)
 static CURLcode tftp_state_machine(tftp_state_data_t *state,
                                    tftp_event_t event)
 {
+  CURLcode res = CURLE_OK;
   struct SessionHandle *data = state->conn->data;
   switch(state->state) {
   case TFTP_STATE_START:
     DEBUGF(infof(data, "TFTP_STATE_START\n"));
-    tftp_send_first(state, event);
+    res = tftp_send_first(state, event);
     break;
   case TFTP_STATE_RX:
     DEBUGF(infof(data, "TFTP_STATE_RX\n"));
-    tftp_rx(state, event);
+    res = tftp_rx(state, event);
     break;
   case TFTP_STATE_TX:
     DEBUGF(infof(data, "TFTP_STATE_TX\n"));
-    tftp_tx(state, event);
+    res = tftp_tx(state, event);
     break;
   case TFTP_STATE_FIN:
     infof(data, "%s\n", "TFTP finished");
@@ -534,9 +547,10 @@ static CURLcode tftp_state_machine(tftp_state_data_t *state,
   default:
     DEBUGF(infof(data, "STATE: %d\n", state->state));
     failf(data, "%s\n", "Internal state machine error");
+    res = CURLE_TFTP_ILLEGAL;
     break;
   }
-  return CURLE_OK;
+  return res;
 }
 
 
@@ -711,8 +725,8 @@ CURLcode Curl_tftp(struct connectdata *conn, bool *done)
         }
 
         /* Update the progress meter */
-        Curl_pgrsUpdate(conn);
-
+        if(Curl_pgrsUpdate(conn))
+          return CURLE_ABORTED_BY_CALLBACK;
       }
     }
 
@@ -731,7 +745,9 @@ CURLcode Curl_tftp(struct connectdata *conn, bool *done)
   }
 
   /* Tell curl we're done */
-  Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+  code = Curl_Transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
+  if(code)
+    return code;
 
   /* If we have encountered an error */
   if(state->error) {