Remove first words from file - c

sorry if this is a dumb question, but I'm kind of inexperienced with C. I'm trying to create a simple TCP client/server connection. This is how it works: the server stores several files, including .txt and .jpg. When the client wants one of them, he sends the name of the file to the server, reading and writing it to a certain location.
Everything works fine, except for the fact that the server's response is "RES status size data" . I'm only interested in the data to create the new file, but I'm not being able to deny the writing of RES status size into the output file. I tried to use strtok but am getting a segfault because of it, dunno why. This is the section of code where I receive the response from the server and start writing it to a new file fp.
while(success == 0)
{
while(f_block_sz = recvfrom(fd2, buffer, sizeof(buffer), 0, (struct sockaddr*)&serveraddr2, &addrlen))
{
if(f_block_sz < 0)
{
printf("Receive file error.\n");
break;
}
int write_sz = fwrite(buffer, sizeof(char), f_block_sz, fp);
if(write_sz < f_block_sz)
{
printf("File write failed.\n");
break;
}
bzero(buffer, LENGTH);
}
printf("ok!\n");
success = 1;
fclose(fp);
}
I don't even know what's best. Should I remove those "useless" words before writing to the newfile, or should I edit the file after it's finished?
Thanks in advance.

I not sure but i just thought if your "RES status size" is of fixed size, say 'x' bytes then while writing to the output file just skip x bytes of received data...
int write_sz = fwrite(buffer + x, sizeof(char), f_block_sz, fp);
I am not sure this is good practice or even correct, i just gave in my thought.

Related

How to send file and filename through socket in C?

I am trying to send a file and its name through a socket in C.
The relevant server code is:
char file[18];
memset(file, 0, 18);
file[17] = '\0';
int recvd = recv(newsock, file, 16, 0);
char local_file_path[200];
memset(local_file_path, 0, 200);
if(recvd == -1 || recv == 0) {
fprintf(stderr, "File name not received");
continue;
}
strcat(local_file_path, "/home/ubuntu/results/");
strcat(local_file_path, file);
FILE* fp = fopen(local_file_path, "wb");
char buffer[4096];
while(1)
{
recvd = recv(newsock, buffer, 4096, 0);
fwrite(buffer, sizeof(char), recvd, fp);
if(recvd == -1 || recvd == 0) {
fclose(fp);
break;
}
}
close(newsock);
}
close(servSock);
The relevant client code is:
char* my_16_long_fname = "filename1234.txt"
int ret = send(sock, my_16_long_file_fname, strlen(my_16_long_fname), 0)
This code, however, has been creating lots of undefined behaviour such as:
1.Receiving garbage filenames filled with garbage
2.Receiving empty files (so a name with nothing inside - could be some other bug but possibly due to this)
I have thought about a few solutions:
1.Diferentiate file types by signature/header and generate a file name on the server side. Besides this being a cheap solution which doesn't teach me how to actually solve the problem, it doesn't work with the logic i'm using, where sometimes I send error codes instead of file names after opening the socket.
2.Iterate over the recv'd buffer on the first call to recv until I encounter a '\0' character. Then write the remainder of the buffer as binary data and keep on receiving data as usual.
Is this the most efficient/simplest and solid solution to this issue, which will prevent any undefined behaviour?
There is no way your current code could possibly work. If the filename is always one character, your code can read too many characters. If your filename is always the same number of characters but more than one character, your code can read too few characters. If the filename is a variable number of characters, your code could read a smaller number than was sent.
So there is no sending protocol for which this could be valid receiving code.
Until you are an expert on writing networking code, always follow these two steps:
Document the protocol.
How many bytes does the filename occupy? Is it a fixed number or a variable number? Is it always followed by a zero byte?
Implement the protocol.
For example, your code reads up to 16 bytes for the filename. But it never checks if it received the whole file name. What if it only received a single byte?

C HTTP Client Receive .PNG File

So I'm writing this simple HTTP Client in C, and, well, I don't know C that well. Here's the gist of it. I got the HTTP client working, I can send the GET request and a get response back. I even can parse the HTTP headers to get the information I want (though my solution to that is admittedly inelegant). The problem is when it's binary information, like a picture file. I'm sure it's something simple, but ... well here's a slimmed down version of what I have.
FILE *fp = fopen("output", "wb"); // Open the file for writing
while (recv(s, buf, MAXDATASIZE - 1, 0) > 0) { //This just iterates over our HTTP response, it works don't worry
if (is_text == 1) { // Assume I already parsed the headers and know the Content-type
fprintf(fp, "%s", buf); // This works, it just writes the text to our output file
}
else { // Anything not text, this is where the problem is
fwrite(buf, sizeof buf, 1, fp); // <-- **This is the problem line**
}
memset(buf, 0, MAXADATASIZE -1, 0); // Reset the buffer, for the next iteration
}
flose(fp); // Close the file
So, the line I have marked as the problem line does write some binary stuff to my output file, it just never matches the original file. Not only do they differ, they differ in size by like orders of a hundred. It's just not the same file. Yes, I know need to figure out a way to strip the headers or the files will always be different, but clearly that's not even the problem here, yet.
--
Extra information:
    Ubuntu 18.04.5
    gcc version 7.5.0
    "Hardware" is a virtualbox VM, 64-bit
recvreturns the number of bytes read.
ssize_t rb;
FILE *fp = fopen("output", "wb"); // Open the file for writing
while ((rb = recv(s, buf, sizeof(buf), 0)) > 0) { //This just iterates over our HTTP response, it works don't worry
fwrite(buf, 1, rb, fp); // <-- **This is not the problem line anymore**
}
flose(fp); // Close the file

Why does my server only write the first line of a file to my client?

I have two programs, a simple client, and a simple server, and I'm trying to send HTTP GET requests from my client to my server. In this case, I am sending a GET /index.html HTTP/1.1\r\n\r\n request from my client to my server, and I have the server send the contents of index.html to my client for it to output to stdout. I have managed to do most of this, EXCEPT that the client outputs only the first line of my index.html file to stdout, and I just cannot see why. What is confusing to me is that, as opposed to this, the printf() in my server program is printing the entire index.html. Here is a snippet from the server program:
#include "csapp.h"
int MAXLEN = 10000;
int main(int argc, char* argv[]){
//some initializations and other things
if(( in = fopen(req, "r")) == NULL){
rio_writen(connfd, "Couldn't open file\n", MAXLEN);
exit(0);
}
while (fgets(output, 99999, in) != NULL){
printf("%s", output); //printing entire thing
write(connfd, output, sizeof(output)); //should write entire file!
}
fclose(in);
Close(connfd);
}
exit(0);
}
And just in case, from my client program, this is how my client reads from my server, although I doubt this is where the problem is happening, as I can read for example, the entire index.html from wwww.google.com just fine, which makes things even more confusing.
int n = Rio_readlineb(&reeo, buffer, MAXLEN);
while(n > 0){
printf("%s", buffer);
n = Rio_readlineb(&reeo, buffer, MAXLEN);
}
Close(fd);
exit(0);
I would greatly appreciate it if anyone can let me know what is going wrong. Also, csapp.c can be found here.
Change your loop to:
while (fgets(output, sizeof(output), in) != NULL){
printf("%s", output); //printing entire thing
write(connfd, output, strlen(output));
}
You should use sizeof when reading from the file, to ensure that it doesn't try to read more than the buffer size. But when writing, you should only write the part of buffer containing the line that was just read. Your code was writing the entire buffer, which includes all the uninitialized bytes.

C sockets receive file

I'm developing very simple ftp client. I have created a data connection sockets, but I can't transfer file successfully:
FILE *f = fopen("got.png", "w");
int total = 0;
while (1){
memset(temp, 0, BUFFSIZE);
int got = recv(data, temp, sizeof(temp), 0);
fwrite(temp, 1, BUFFSIZE, f);
total += got;
if (total == 1568){
break;
}
}
fclose(f);
BUFFSIZE = 1568
I know that my file is 1568 bytes size, so I try to download it just for a test. Everything is file when I try to download .xml or .html files, but nothing good happens when I try to download png or avi files. Simply original file size is 1568 but got.png file size is 1573. I can't figure out what might cause that.
EDIT:
I have modified my code, so now it looks like (it can accept any file size):
FILE *f = fopen("got.png", "w");
while (1){
char* temp = (char*)malloc(BUFFSIZE);
int got = recv(data, temp, BUFFSIZE, 0);
fwrite(temp, 1, got, f);
if (got == 0){
break;
}
}
fclose(f);
Still received file is 2 bytes too long.
You are opening the file in text mode, so bare CR/LF characters are going to get translated to CRLF pairs when written to the file. You need to open the file in binary mode instead:
FILE *f = fopen("got.png", "wb");
You are always writing a whole buffer even if you have received only a partial one. This is the same problem with ~50% of all TCP questions.
The memset is not necessary. And I hope that temp is an array so that sizeof(temp) does not evaluate to the native pointer size. Better use BUFFSIZE there as well.
Seeing your edit, after fixing the first problem there is another one: Open the file in binary mode.

c read() causing bad file descriptor error

Context for this is that the program is basically reading through a filestream, 4K chunks at a time, looking for a certain pattern. It starts by reading in 4k, and if doesn't find the pattern there, it starts a loop which reads in the next 4k chunk (rinse and repeat until EOF or pattern is found).
On many files the code is working properly, but some files are getting errors.
The code below is obviously highly redacted, which I know might be annoying, but it includes ALL lines that reference the file descriptor or the file itself. I know you don't want to take my word for it, since I'm the one with the problem...
Having done a LITTLE homework before crying for help, I've found:
The file descriptor happens to always = 6 (it's also 6 for the files that are working), and that number isn't getting changed through the life of execution. Don't know if that's useful info or not.
By inserting print statements after every operation that accesses the file descriptor, I've also found that successful files go through the following cycle "open-read-close-close" (i.e. the pattern was found in the first 4K)
Unsuccessful files go "open-read-read ERROR (Bad File Descriptor)-close." So no premature close, and it's getting in the first read successfully, but the second read causes the Bad File Descriptor error.
.
int function(char *file)
{
int len, fd, go = 0;
char buf[4096];
if((fd = open(file, O_RDONLY)) <= 0)
{
my_error("Error opening file %s: %s", file, strerror(errno));
return NULL;
}
//first read
if((len = read(fd, buf, 4096)) <= 0)
{
my_error("Error reading from file %s: %s", file, strerror(errno));
close(fd); return NULL;
}
//pattern-searching
if(/*conditions*/)
{
/* we found it, no need to keep looking*/
close(fd);
}
else
{
//reading loop
while(!go)
{
if(/*conditions*/)
{
my_error("cannot locate pattern in file %s", file);
close(fd); return NULL;
}
//next read
if((len = read(fd, buf, 4096)) <= 0) /**** FAILS HERE *****/
{
my_error("Error reading from file, possible bad message %s: %s",
file, strerror(errno));
close(fd); return NULL;
}
if(/*conditions*/)
{
close(fd);
break;
}
//pattern searching
if(/*conditions*/)
{
/* found the pattern */
go++; //break us out of the while loop
//stuff
close(fd);
}
else
{
//stuff, and we will loop again for the next chunk
}
} /*end while loop*/
}/*end else statement*/
close(fd);
}
.
Try not to worry about the pattern-reading logic - all operations are done on the char buffer, not on the file, so it ought to have no impact on this problem.
EOF returns 0 (falls into if ... <= 0), but does not set errno, which may have an out of date code in it.
Try testing for 0 and negative (error, -1) values seperately.
Regarding "strace": I've used it a little at home, and in previous jobs. Unfortunately, it's not installed in my current work environment. It is a useful tool, when it's available. Here, I took the "let's read the fine manual" (man read) approach with the questioner :-)

Resources