How many structs go into a file? in c - c

I need to open a file that contains information and map that data using mmap. The data will be accessed by casting the mmap call with a struct. The problem is the file has information to fill approximately 3 structs because the data is repeated. So I need to access that information in chunks, I don't know if the explanation makes any sense.
The file has 384 bytes and the struct covers 128 bytes so I will need something like 3 structs in total.
I don't know how to do that. I already have mapped the file and printed the first struct.
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <unistd.h>
#include <sys/types.h>
#include <stdbool.h>
struct mapped
{
/* Struct fields */
};
int main (int argc, char **argv){
int fd = open("file",O_RDONLY,S_IRUSR | S_IWUSR);
struct stat st;
if(fstat(fd,&st)==-1) perror("Error\n");
struct mapped *data = mmap(0,st.st_size,PROT_READ | PROT_WRITE,MAP_PRIVATE,fd,0);
printf("\n");
printf("File size: %li",st.st_size);
printf("\n");
printf(": %li",st.st_size);
printf("\n");
printf("\n");
// print the struct data;
printf("\n");
close(fd);
munmap(data,st.st_size);
exit(EXIT_SUCCESS);
}

Related

what is the different between struct stat * buffer and &buffer in linux stat function

I am trying to get the parent directory stats.
If I wrtie code like below it return error: Bad address
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <dirent.h>
int main(int agrc, char * argv[]){
struct stat *buffer;
int res = stat("..", buffer);
if(res != 0){
perror("error");
exit(1);
}
//printf("%d", buffer->st_ino);
}
But If I write code like this below, there is no problem.
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <stdlib.h>
#include <dirent.h>
int main(int agrc, char * argv[]){
/* struct stat *buffer; */
struct stat buffer;
int res = stat("..", &buffer);
if(res != 0){
perror("error");
exit(1);
}
//printf("%d", buffer->st_ino);
printf("%d", buffer.st_ino);
}
I do not know why the result is different.
The variable buffer of definition struct stat * buffer is a pointer of struct stat
The &buffer is also a pointer of struct stat
The function is defined as below in manpage
SYNOPSIS
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int stat(const char *pathname, struct stat *buf);
...
I expected the result to be both successful, why the result is different? anyone can help, thanks a lot.
With struct stat buffer; , there is memory allocated for buffer on the stack.
But with struct stat *buffer; there is no memory allocated for buffer. You have to use a memory allocation function to allocate memory. This allocation happens on what is known as heap.
struct stat *buffer = malloc(sizeof(struct stat));
Note that stat() stats the file pointed to by path and fills in buf. So if buf does not point to memory that the program owns, it will result in error: Bad address.

c - can't understand pthread_join()

I can not figure out where I'm wrong, after running the code arrived in the for where it runs the pthread_join() , many pthread_join() return with value 3 instead of 0. Furthermore, printing the value of i is not always consistent and this causes segmentation fault and printing several times of the same position.
Code modified as required in the comments
all the includes are for other parts of the program. Testing only this piece of code creates segmentation fault at error 3 on pthread_join()
#define _POSIX_C_SOURCE 200809L
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <string.h>
#include <signal.h>
#include <pthread.h>
#include <errno.h>
#include <config.h>
#include <sys/select.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
void *threadF(){
printf("hello\n");
pthread_exit((void*)0);
}
int main(int argc, char *argv[]) {
FILE *fileconf=fopen(argv[2],"r");
if(fileconf==NULL){
fprintf(stderr, "Fopen\n",argv[2]);
return -1;
}
set_conf(fileconf); //parse fileconf and set THREADSINPOOL correctly
pthread_t array[THREADSINPOOL];
int i,err,s=0;
for(i=0;i<THREADSINPOOL;i++){
if((err=pthread_create(&array[i],NULL,&threadF,NULL))!=0){
fprintf(stderr,"thread\n");
exit(errno);
}
}
int tmp;
for(i=0;i<THREADSINPOOL;i++){
tmp=pthread_join(array[i],(void *)&s);
printf("thread: %lu terminated\n tmp: %d\n",array[i],tmp);
}
return 0;
}
The problem is that you are passing the address of an int to a function that expects the address of a void *. On a 64-bit system, there's a good chance that an int is only 32-bits whereas a void * is 64-bits. So pthread_join ends up writing 64-bits into a location that is only big enough for 32-bits. The result is that you overwrite memory that shouldn't being changed, and all sorts of undefined behavior follows.
Here's a way to write the code so that the second argument to pthread_join is actually a pointer to a void *
for (i = 0; i < THREADSINPOOL; i++)
{
void *value;
if (pthread_join(array[i], &value) == 0)
printf("thread %d returned %" PRIiPTR "\n", i, (intptr_t)value);
else
printf("thread %d failed\n", i);
}

Read a RAID device directly using read(2)

I have create a Linux Software RAID, with chunk size 4096B, and 4 disks.
Then, I'm trying to do write and read test on the RAID, say /dev/md0.
The following code is read test and BLOCK_SIZE is the amount I want to read. However, whenever I set it not power of 2, such as 3*4096, I will get an error after read, saying "Invalid Argument". And it is the same case with write.
As far as I can understand, read(2) and write(2) should be able to perform operation on any amount of bytes the user wants, so please help me with it and the code.
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#define BLOCK_SIZE 8*4096 //bytes
#define BUFF_OFFSET 8*4096
int main(int argc, char *argv[]){
char device[64];
int fd;
void *buff;
int size; //bytes
int seek;
fd = open(argv[1], O_DIRECT | O_RSYNC | O_RDONLY);
posix_memalign(&buff, BUFF_OFFSET, BLOCK_SIZE);
int load;
seek = lseek(fd,0,SEEK_SET);
load = read(fd,buff,BLOCK_SIZE);
if (load < 0){
printf("Cannot read\n");
perror("because");
break;
}
else{
printf("%d\n",load);
}
close(fd);
return 0;
}

Whether a given file argument is a directory or not. C

I am looking for a peace of code to check if the argument I pass to my program is a directory or not. So far I found this:
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
struct stat buf;
stat(argv[1],&buf);
exit(0);
}
But it does not really help me.
Use:
if(S_ISDIR(buf.st_mode))
printf(" Its a directoy\n");
else
printf("Its a file\n");
after stat(argv[1],&buf); call

stat gives No such file or directory

I have the following code in C. I run it at FreeBSD. I compile it as cc -o bbb bb.c. Then run and get the output
$ ./bbb
-1
stat: No such file or directory
This is the Code:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <fcntl.h>
#include <string.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
int main() {
struct stat *st;
int stat_code =0;
stat_code = stat("/", st);
printf("%d\n", stat_code);
perror("stat");
return 0;
}
int stat(const char *restrict path, struct stat *restrict buf);
The stat() function shall obtain information about the named file and write it to the area pointed to by the buf argument. The path argument points to a pathname naming a file.
In your code stat("/", st); is path for directory only.
This the the function prototype for stat() from man 2 stat
int stat(const char *path, struct stat *buf);
Your code will get segmentation fault, because address of structure variable need to pass in stat() function.
Code:
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
int main() {
struct stat st;
int stat_code =0;
stat_code = stat("test.txt", &st);
printf("%d\n", stat_code);
perror("stat");
return 0;
}
above will help you. For reference
man 2 stat

Resources