my read functions reads data out of my file - c

so I'm working on a project where I have to read BUFFER_SIZE bytes (which will be defined as a macro during the compilation) from a file on each call, and the allowed functions are {read(),malloc()} and when I use my code in the case below it reads the file plus some data I don't know where it came from, BUFFER_SIZE = 10 in this case
file contains :
01234567890123456789012345678901234567890
1
code :
#include <unistd.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
int main()
{
int fd;
char *buff;
int r;
buff=(char *) malloc((BUFFER_SIZE + 1) * sizeof(char));
fd = open("test", O_RDONLY);
r = 1;
while (r)
{
printf("BEFORE : %d\n",r);
r = read(fd, buff, BUFFER_SIZE);
printf("AFTER : %d\n",r);
buff[r] = '\0';
printf("%s\n",buff);
}
}

Related

Why do I get segmentation fault using fopen?

I'm writing a client-server model in C which works using fifos. I send a file name plus a name for a unique fifo for the client to recieve the data from the client and the server opens the file and writes the first line of it on the fifo. The thing is that even if the file exists i get a segmentation fault when opening it. Seems like the fopen() function works but I still get the error. If the file doesn't exist it just sends an empty string.
Here is client.c :
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#define BUFSIZE 512
struct sent {
char name[BUFSIZE];
char fifo[BUFSIZE];
};
int main()
{
char name[BUFSIZE];
char recieved[BUFSIZE];
int client_server_fifo;
char cs_fifo[BUFSIZE] = "cs_fifo";
int server_client_fifo;
char sc_fifo[BUFSIZE];
sprintf(sc_fifo, "sc_fifo_%d", getpid());
struct sent *sent;
mkfifo(sc_fifo, 0777);
while(1) {
printf("Write the name of the file: ");
scanf("%s", name);
printf("1111\n");
client_server_fifo = open(cs_fifo, O_WRONLY);
printf("2222\n");
printf("%s", name);
printf("%s", cs_fifo);
sent->name = name;
sent->fifo = cs_fifo;
printf("%s", name);
printf("%s", cs_fifo);
write(client_server_fifo, sent, sizeof(*sent));
server_client_fifo = open(sc_fifo, O_RDONLY);
if (read(server_client_fifo, recieved, sizeof(recieved)) == -1) {
printf("An error ocurred.\n");
} else {
printf("First line of the file: \n%s\n", recieved);
close(client_server_fifo);
close(server_client_fifo);
}
memset(recieved, 0, sizeof(recieved));
}
return 0;
}
And here's server.c :
#include <fcntl.h>
#include <stdio.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <errno.h>
#include <stdlib.h>
#define BUFSIZE 512
struct sent {
char name[BUFSIZE];
char fifo[BUFSIZE];
};
int main()
{
int client_server_fifo;
char cs_fifo[BUFSIZE] = "cs_fifo";
int server_client_fifo;
char sc_fifo[BUFSIZE];
struct sent *sent;
char name[BUFSIZE];
char line[BUFSIZE];
FILE *file;
printf("Server running...\n");
mkfifo(cs_fifo, 0777);
while (1)
{
client_server_fifo = open(cs_fifo, O_RDONLY);
read(client_server_fifo, sent, sizeof(*sent));
strcpy(name, sent->name);
strcpy(sc_fifo, sent->fifo);
if((file = fopen(name, "r")) != NULL) {
printf("%s\n", name);
fgets(line, BUFSIZE, file);
printf("%s\n", name);
}
server_client_fifo = open(sc_fifo, O_WRONLY);
write(server_client_fifo, line, strlen(line));
memset(name, 0, sizeof(name));
memset(line, 0, sizeof(line));
close(client_server_fifo);
}
return 0;
}
Why does this happen?
The program has undefined behavior because in gthis statement
sprintf(sc_fifo, "sc_fifo_%d", getpid());
you are trying to change a string literal pointed to by the pointer sc_fifo.
char *cs_fifo = "cs_fifo";
When you declare a pointer to a string literal always declare them with the qualifier const. In this case you will get ban error at compilation time if you will tray to change a string literal.
Also you are using uninitialized pointer sent
struct sent *sent;
in this statement
read(client_server_fifo, sent, sizeof(*sent));
There are other errors. For example arrays do not have the assignment operator. So these statements in client.c
sent->name = name;
sent->fifo = cs_fifo;
are incorrect.

Trying to write a buffer to a file, but keep getting segmentation faults and I can't figure out why

I have some code whose goal is to open/create a file, read in messages, and then write those messages to the opened/created file. Everything up to the writing to the file seems to work just fine. Here is my code.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <stdlib.h>
#include <pthread.h>
#include <semaphore.h>
#include "message-lib.h"
int usage( char name[] );
void * recv_log_msgs( void * arg );
sem_t mutex;
int log_fd;
void * recv_log_msgs( void * arg ){
sleep(1);
sem_wait(&mutex);
char buffer[1024];
int number_bytes_read;
FILE *fp = log_fd;
do{
number_bytes_read = read_msg(arg, buffer, 1024);
printf("in recv\n");
printf(buffer);
fwrite(&buffer, 1, sizeof(buffer)/sizeof(buffer[0]), fp);
}while(number_bytes_read > 0);
if(number_bytes_read == 0){
close_connection(arg);
}
sem_post(&mutex);
return NULL;
}
int usage( char name[] ){
printf( "Usage:\n" );
printf( "\t%s <log-file-name> <UDS path>\n", name );
return 1;
}
int main( int argc, char * argv[] )
{
int connection;
pthread_t tid;
if ( argc != 3 )
return usage( argv[0] );
log_fd = creat(argv[1], S_IRUSR | S_IWUSR);
if(log_fd == -1){
perror(argv[1]);
return 1;
}
int listener = permit_connections(argv[2]);
if(listener == -1){
return -1;
}
sem_init(&mutex, 0, 1);
do{
connection = accept_next_connection(listener);
if(connection == -1){
return -1;
}
pthread_create(&tid, NULL, recv_log_msgs, connection);
}while(connection != -1);
close_connection(connection);
close_listener(listener);
fclose(log_fd);
return 0;
}
permit_connections, accept_next_connection, and read_msg are all from a library that was provided to me. I'm guessing my problem is in recv_log_msgs, but I'm not sure what it would be.
Here's the root of your problem:
FILE *fp = log_fd;
log_fd is a file descriptor, fp is a FILE pointer.
The two are not interchangeable, and what you need to do is use the write(...) system call for writing to the log file, or create the log file in some other fashion to get a hold of a FILEpointer to it.
FILE *fp = fopen(argv[1], "w"), might do the trick.
EDIT: As #DarrenSmith pointed out to me in the comments, you can also use
fp = fdopen(log_fd, "w")
and keep the rest of the code as is.

Hashing program not returning identical values for the same file

This hashing function I've created (that scans for new files, and computes their hashes) seemingly functions, however once removing a file, for example test.c, and then replacing it with the exact same file it returns 2 different hash values. By this I mean that whilst the program is running the first calculation might return a hash of 1234, for example, and once deleting and placing the same file within the folder the it then returns 2345.
There seems to be no order, as 1234 could be the result 5 times in a row. I wondered whether there's any strikingly obvious reason in this code?
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/inotify.h>
#include <openssl/sha.h>
int main (int argc, char *argv[])
{
int fd;
unsigned char c[SHA512_DIGEST_LENGTH];
int i;
SHA512_CTX mdContext;
int bytes;
unsigned char data[1024];
const int event_size = sizeof(struct inotify_event);
const int buf_len = 1024 * (event_size + FILENAME_MAX);
char *directory = "/home/joe/Documents/";
char *hashDirectory = "/home/joe/Documents/_Hash/";
char hashInBuf[100];
char hashOutBuf[100];
fd = inotify_init();
if (fd < 0) {
perror("inotify_init");
}
while (1) {
char buff[buf_len];
int no_of_events, count = 0;
//SEARCH FOR NEW FILES WITHIN DIRECTORY
no_of_events = read (fd, buff, buf_len);
while (count < no_of_events) {
struct inotify_event *event = (struct inotify_event *)&buff[count];
if (event->len) {
if ((event->mask & IN_CREATE))
if(!(event->mask & IN_ISDIR)) {
printf("\n%s has been created\n", event->name);
//CONJOIN DIRECTORY AND FILENAME / EXTENSION
snprintf(hashInBuf, sizeof(hashInBuf), "%s/%s", directory, event->name);
snprintf(hashOutBuf, sizeof(hashOutBuf), "%s/%s.txt", hashDirectory, event->name);
FILE *ftest=fopen(hashInBuf, "rb");
FILE *ftest2=fopen(hashOutBuf, "wt");
//HASH FUNCTION
SHA512_Init (&mdContext);
while ((bytes = fread (data, 1, 1024, ftest)) != 0)
SHA512_Update (&mdContext, data, bytes);
SHA512_Final (c,&mdContext);
for(i = 0; i < SHA512_DIGEST_LENGTH; i++){
fprintf(ftest2, "%02x", c[i]);
printf("%02x", c[i]);
}
fclose (ftest);
fclose (ftest2);
fflush (stdout);
}
}
count += event_size + event->len;
}
}
return 0;
}
Thank you in advance!
In this line
if ((event->mask & IN_CREATE))
you wait for the event that a file is created. Then, your hashing function immediately starts running!
This may lead to the situation that the file is not fully written yet, so you only hashed a part of the file.
You should use the event IN_CLOSE_WRITE to make sure, that the file has already been completely written.
Another option is to not create the files in this directory, but creating them in a temporary directory and subsequently moving them into the target directory. The corresponding event is IN_MOVED_TO then.

how to print name of newly created file(s) within a directory in C?

This code scans for newly created files within a directory, however where "%s" should contain the name of the new file(s) this does not occur.
I can imagine there are unnecessary pieces of code written here, however being quite unfamiliar with C I'm simply happy it compiles at this point (and actually recognizes new files) !
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/inotify.h>
int main (int argc, char *argv[])
{
char target[FILENAME_MAX];
int result;
int fd;
int wd; /* watch descriptor */
const int event_size = sizeof(struct inotify_event);
const int buf_len = 1024 * (event_size + FILENAME_MAX);
fd = inotify_init();
if (fd < 0) {
perror("inotify_init");
}
wd = inotify_add_watch(fd, "/home/joe/Documents", IN_CREATE);
while (1) {
char buff[buf_len];
int no_of_events, count = 0;
no_of_events = read (fd, buff, buf_len);
while (count < no_of_events) {
struct inotify_event *event = (struct inotify_event *)&buff[count];
if (event->len) {
if (event->mask & IN_CREATE)
if(!(event->mask & IN_ISDIR)) {
printf("The file %s has been created\n", target);
fflush(stdout);
}
}
count += event_size + event->len;
}
}
return 0;
}
You're printing out target when you get an event, however target is never modified.
The name of the created file is stored in event->name. That's what you want to print.
printf("The file %s has been created\n", event->name);

POSIX read() function does not read any bytes when lseek() is called

I have the following program
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <sys/stat.h>
int main(int argc, char* argv[]) {
int fd;
char buffer[100];
// open notes file
fd = open("/var/testfile", O_RDONLY);
if(fd == -1) {
error("in main() while opening file for reading");
}
int readBytes = 0;
// read 10 bytes the first time
readBytes = read(fd, buffer, 10);
buffer[10] = 0;
printf("before lseek: %s\n readBytes: %d\n", buffer, readBytes);
// reset buffer
int i = 0;
for(i = 0; i < 10; i++) {
buffer[i] = 0;
}
// go back 10 bytes
lseek(fd, -10, SEEK_CUR);
// read bytes second time
readBytes = read(fd, buffer, 10);
buffer[10] = 0;
printf("after lseek: %s\n readBytes: %d\n", buffer, readBytes);
}
And the following content in the /var/testfile:
This is a test.
A second test line.
The output of the program:
before lseek: This is a
readBytes: 10
after lseek:
readBytes: 0
I don't unerstand why after the lseek() call the read() function does not read any bytes. What is the reason for this? I would expect the same result as I get from the first read() function call.
My compiler says "xxc.c:33:5: warning: implicit declaration of function ‘lseek’ [-Wimplicit-function-declaration]"
This means that the second argument will be assumed to be an integer (probably 32bits), but the definition is actually for the type "off_t" which on Linux or Windows will be a longer 64bit integer.
This means the offset you're giving it is likely to be VERY large and well past the end of your testfile.
The manual says that for lseek() you need the headers:
#include <sys/types.h>
#include <unistd.h>

Resources