1

This is a snippet of the LIST ftp's cmd:

count = file_list("./", &files); if((fp_list = fopen("listfiles.txt", "w")) == NULL){ perror("Impossibile aprire il file per la scrittura LIST"); onexit(newsockd, sockd, 0, 2); } for(i=0; i < count; i++){ if(strcmp(files[i], "DIR ..") == 0 || strcmp(files[i], "DIR .") == 0) continue; else{ fprintf(fp_list, "%s\n", files[i]); } } fclose(fp_list); if((fpl = open("listfiles.txt", O_RDONLY)) < 0){ perror("open file with open"); onexit(newsockd, sockd, 0, 2); exit(1); } if(fstat(fpl, &fileStat) < 0){ perror("Errore fstat"); onexit(newsockd, sockd, fpl, 3); } fsize = fileStat.st_size; if(send(newsockd, &fsize, sizeof(fsize), 0) < 0){ perror("Errore durante l'invio grande file list"); onexit(newsockd, sockd, fpl, 3); } rc_list = sendfile(newsockd, fpl, &offset_list, fileStat.st_size); if(rc_list == -1){ perror("Invio file list non riuscito"); onexit(newsockd, sockd, fpl, 3); } if((uint32_t)rc_list != fsize){ fprintf(stderr, "Error: transfer incomplete: %d di %d bytes inviati\n", rc_list, (int)fileStat.st_size); onexit(newsockd, sockd, fpl, 3); } printf("OK\n"); close(fpl); if(remove( "listfiles.txt" ) == -1 ){ perror("errore cancellazione file"); onexit(newsockd, sockd, 0, 2); } 

wher &files is declared as char **files and the function list_files is a function written by me that isn't relevant for my problem.
My problem: the first time LIST cmd it's called it works properly but if i call LIST another time it always give me "error, transfer incomplete" i don't understand why...

4
  • 1
    Is the "error, transfer incomplete" message seen from the code you posted in your question? When in that case? Otherwise, what does the code in the question report? Commented Aug 8, 2012 at 8:02
  • yes, it is what i've posted into the question :) it give me an error when the sendfile function doesn't send all the file... Commented Aug 8, 2012 at 8:38
  • What is offset_list and how do you initialize it? Remember that if sendfile can't send everything then it will return a value less than the requested size, and you will have to adjust the size and try again. Commented Aug 8, 2012 at 8:45
  • offset_list is initialized with offset_t...so i have to do this? send: if((uint32_t)rc_list != fsize){ fprintf(stderr, "Error: transfer incomplete: %d di %d bytes inviati\n", rc_list, (int)fileStat.st_size); goto send; } Commented Aug 8, 2012 at 8:51

2 Answers 2

7

The sendfile function may not send all data in one call, in which case it will return a number less than requested. You treat this as an error, but instead you should try again. One way is to use a loop similar to this:

// Offset into buffer, this is where sendfile starts reading the buffer off_t offset = 0; // Loop while there's still some data to send for (size_t size_to_send = fsize; size_to_send > 0; ) { ssize_t sent = sendfile(newsockd, fpl, &offset, size_to_send); if (sent <= 0) { // Error or end of file if (sent != 0) perror("sendfile"); // Was an error, report it break; } size_to_send -= sent; // Decrease the length to send by the amount actually sent } 
Sign up to request clarification or add additional context in comments.

4 Comments

oh thanks :) i've posted my answer without see yours! However i've found my problem but your solution is better :)
but if sent is <= 0 i have to exit and close the socket...why you do only a break??
@polslinux You can do whatever you want in your code. The break is just an example.
Will the sendfile not set offset propertly? Do we need to do offset += sent;
2

I've found my problem.
When i call sendfile multiple times the variable off_t offset_list; remains "dirty".
If a call sendfile the 1st time offest_list will have a value that won't be deleted the 2nd time i call that function.
So if i have to write offset_list = 0; before rc_list = sendfile(newsockd, fpl, &offset_list, fileStat.st_size); and all work!

1 Comment

it also fixed my problem!!! and I was into it for entire days !!! I can't say how much I'm happy right now. THANKS

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.