My program has a loop that runs initUSB() and then runs writeEssentials() multiple times.
initUSB() is a function that mounts the USB to a directory.
writeEssentials() is a function that opens a file, and appends it with data, and then closes the file.
After a minute or so after the initial run of the program, the program will report that the file system is "read only", and will refuse to write anymore data, until initUSB() is run again. This happens weather or not I fprintf() into the file pointer. As a temporary solution, I made writeEssentials() remount the drive if it becomes read-only. This works, but I would rather not remount the drive every minute.
Why does this happen, and how can I fix this error?
The program is running on an Debian embedded Linux system, on a TS-7800.
InitUSB:
int initUSB(){
int i;
FILE * filecheck = fopen(HMITelemCheckFile, "r");
for(i = 0; i < 26; i++) {
char usbMountFromPathTry[256];
char sdanum[5];
strcpy(usbMountFromPathTry, usbMountFromPath);
sprintf(sdanum, "%c1", i+'a');
strcat(usbMountFromPathTry, sdanum);
if(!mount(usbMountFromPathTry, usbMountToPath, "vfat", (long)NULL, NULL)){
printf("Mount successful\n");
return 1;
} else if(!mount(usbMountFromPathTry, usbMountToPath, "vfat", MS_REMOUNT, NULL)){
printf("Mount successful\n");
return 1;
}
printf("Mount error: ");
printf("%s\n", usbMountFromPathTry);
}
printf("Mount ERROR\n");
return 0;
}
writeEssentials():
void writeEssentials(){
FILE * file = fopen(usbMountEssentials, "a+");
fflush(file);
perror("file");
if(file == NULL){
initUSB();
printf("null file\n");
return;
}
fprintf(file, "\n%s, ", getDate());
fprintf(file, "%s, ", getTime());
fprintf(file, "%1.2f, ", getSpeed());
fprintf(file, "%d, ", getRPM());
fprintf(file, "%d, ", getRegen());
fprintf(file, "%d, ", getAirgap());
fprintf(file, "%d, ", getBattery());
fprintf(file, "%.2f, ", *(getADCTemps()+COMPUTER_BOX_TEMP_INDEX));
fprintf(file, "%.2f, ", *(getBMS()+BMS_TEMP_INDEX+(BMS_NUM_VAR*0)));
fprintf(file, "%.2f, ", *(getBMS()+BMS_TEMP_INDEX+(BMS_NUM_VAR*1)));
fprintf(file, "%.2f, ", *(getBMS()+BMS_TEMP_INDEX+(BMS_NUM_VAR*2)));
fprintf(file, "%.2f, ", *(getMPPT()+MPPT_TEMP_INDEX+(MPPT_NUM_VAR*0)));
fprintf(file, "%.2f, ", *(getMPPT()+MPPT_TEMP_INDEX+(MPPT_NUM_VAR*1)));
fprintf(file, "%.2f, ", *(getMPPT()+MPPT_TEMP_INDEX+(MPPT_NUM_VAR*2)));
fprintf(file, "%.2f, ", *(getMPPT()+MPPT_TEMP_INDEX+(MPPT_NUM_VAR*3)));
fprintf(file, "%s, ", getLat());
fprintf(file, "%s, ", getLong());
int i;
for(i = 0; i < getNumErrors(); i++){
//fprintf(file, "%s, ", getErrorText(*(getErrors()+i)));
}
fclose(file);
perror("close file error");
}
Check dmesg. Filesystems spontaneously going read-only is usually an indication that there's some corruption that's being detected, so the kernel is setting the FS as read-only to protect it from further damage.
Related
I could use some help passing this file pointer to a thread to have the thread write to an output file. Currently the file is not being written to at all and I am not getting any errors and working.
void *ThreadTwo(void *param){
FILE *outputFile = param;
// Condition for even
if (r == 0) {
fprintf(outputFile, "%d\n", globalValue);
fprintf(outputFile, "%d\n", globalValue);
printf("twice becase it is even\n");
}
else {
fprintf(outputFile, "%d\n", globalValue);
printf("Once because it is odd\n");
}
}
pthread_exit(NULL);
}
int main() {
FILE *outputFile;
outputFile = fopen("hw3.out", "w");
pthread_create(&th[1], NULL, ThreadTwo, &outputFile);
fclose(outputFile);
return 0;
}
Hi I have a C programme that is basacally suppose to simulate the pipe function in linux and write the amount of bytes that are read in a .txt file so
./a.out cat test : grep -v le : wc -l
The problem that I'm trying to figure out is
Why is the same amount of bytes written in the file since I know each process returns a different amount ?
This piece of code is executed in the parent and is trying to count the amount of bytes of each output with a read syscall and writes the output in a write syscall in the next process so that the next process can use the output as his input.
So let's say I have these pipes a | b | c
This code will read the output of a and write it in b so that b can use it as it's input and so on.
for (int i = 1; i < processes-1; i++) {
close(apipe[i][1]);
char str[4096];
int count=0;
int nbChar=0;
while(1){
count=read(apipe[i][0],str,sizeof(str));
nbChar+=count;
if(count==-1){
if (errno == EINTR) {
continue;
} else {
perror("read");
exit(1);
}
}else if(count==0)break;
}
char *leInput=(char*)malloc(nbChar*sizeof(char));
strncpy(leInput,str,nbChar);
if(i>0){
fprintf(fp, "%d : %d \n ", i,nbChar);
}
close(apipe[i][0]);
write(apipe[i+1][1], leInput, nbChar);
}
Each time through the while(1) loop you're read into the beginning of str, not where you left off in the previous iteration. So you're overwriting the previous read with the next read.
You should copy incrementally to leInput each time through the loop. You can then use realloc() to grow it to accomodate the new input, and you can use leInput + nbChar to copy after the place where you finished the previous time.
for (int i = 1; i < processes-1; i++) {
close(apipe[i][1]);
int nbChar=0;
char *leInput = NULL;
while(1){
int count=0;
char str[4096];
count=read(apipe[i][0],str,sizeof(str));
if(count==-1){
if (errno == EINTR) {
continue;
} else {
perror("read");
exit(1);
}
} else if(count==0) {
break;
}
leInput = realloc((nbChar + count)*sizeof(char));
memcpy(leInput + nbChar, str, count);
nbChar += count;
}
if(i>0){
fprintf(fp, "%d : %d \n ", i,nbChar);
}
close(apipe[i][0]);
write(apipe[i+1][1], leInput, nbChar);
}
Alternatively you could just write to the next pipe in the inner loop, without collectiong everything into leInput:
for (int i = 1; i < processes-1; i++) {
int nbChar = 0;
close(apipe[i][1]);
while(1){
int count=0;
char str[4096];
count=read(apipe[i][0],str,sizeof(str));
if(count==-1){
if (errno == EINTR) {
continue;
} else {
perror("read");
exit(1);
}
} else if(count==0) {
break;
}
write(apipe[i+1][1], str, count);
nbChar += count;
}
if(i>0){
fprintf(fp, "%d : %d \n ", i,nbChar);
}
close(apipe[i][0]);
close(apipe[i+1][1])
}
In this code, I just included 5 pathnames. Although the pathnames can increase also. This code is working fine and notifying the filesystem correctly. But my question is that if there are 100s or 1000s of files, then will I have to write if-statement if(event-wd == wd[0]) or switch-statement for each pathname. Is there any short way?
char pathname[5][100] = {"/home/runner/TestC1", "path/to/folder2", "path/to/folder3", "path/to/folder4", "path/to/folder5"};
int main(){
int length, i = 0, fd, wd[5];
char buffer[EVENT_BUF_LEN];
fd = inotify_init();
if (fd < 0){
perror( "inotify_init" );
}
for (int i=0; i<5; i++){
wd[i] = inotify_add_watch( fd, pathname[i], IN_CREATE);
}
length = read( fd, buffer, EVENT_BUF_LEN );
if(length < 0){
perror("read");
}
while(i < length){
struct inotify_event *event = ( struct inotify_event *)&buffer[i];
if(event->len){
if(event->mask & IN_CREATE){
if(event->mask & IN_ISDIR){
if(event->wd == wd[0]){
printf( "New directory %s created in %s\n", event->name, pathname[0]);
}
else if(event->wd == wd[1]){
printf( "New directory %s created in %s\n", event->name, pathname[1]);
}
else if(event->wd == wd[2]){
printf( "New directory %s created in %s\n", event->name, pathname[2]);
}
else if(event->wd == wd[3]){
printf( "New directory %s created in %s\n", event->name, pathname[3]);
}
else if(event->wd == wd[4]){
printf( "New directory %s created in %s\n", event->name, pathname[4]);
}
}
}
}
i += EVENT_SIZE + event->len;
}
for(int i=0; i<5; i++){
inotify_rm_watch(fd, wd[i]);
}
close(fd);
}
You can use for loops.
Instead of this:
if(event->wd == wd[0]){
printf( "New directory %s created in %s\n", event->name, pathname[0]);
}
else if(event->wd == wd[1]){
printf( "New directory %s created in %s\n", event->name, pathname[1]);
}
else if(event->wd == wd[2]){
printf( "New directory %s created in %s\n", event->name, pathname[2]);
}
else if(event->wd == wd[3]){
printf( "New directory %s created in %s\n", event->name, pathname[3]);
}
else if(event->wd == wd[4]){
printf( "New directory %s created in %s\n", event->name, pathname[4]);
}
You can use this:
for(int j = 0; j < 5; j++){
if(event->wd == wd[j]){
printf( "New directory %s created in %s\n", event->name, pathname[j]);
break;
}
}
I have a hidraw.c code below which I use "fprintf" to write the buffer content onto a file but it does not write the stdout to a specified file. File is created but the file is empty. Does anyone know how to approach this issue? Complete source code can be found here:
https://code.woboq.org/linux/linux/samples/hidraw/hid-example.c.html
Below is the code snippet which I need help on. I'm a novice in C prog.
FILE *fp;
int loop = 10;
fp=fopen("test.txt", "a");
while (loop !=0)
{
res = read(fd, buf, 16);
if (res < 0) {
perror("read");
} else {
printf("read() read %d bytes:\n\t", res);
if(fp == NULL)
exit(-1);
for (i = 0; i < res; i++)
/* This printf will print buffer in the real time */
/*printf("%hhx ", buf[i]);*/
/* This is to write buffer to a file but this does not capture the data*/
fprintf(fp, "%hhx ", buf[i]);
}
}
fclose(fp);
close(fd);
regarding;
fprintf(fp, "%hhx ", buf[i]);
Assuming that the call to fopen() was successful
This is placing the bytes from buf[] into the output stream for the output file. But NOT forwarding those bytes to the actual file.
Suggest, after the loop is completed:
fflush( fp );
I was trying to implement FTP Server as a part of an assignment and I wrote the following code to implement GET Command, which essentially reads file1 from server and stores it in file2.
int getCommandImpl(int clientSocket, char *file1, char *file2){
char *messageContent;
char buffer[256], userCommand[256], *tempString ;
int messageHead, endOfTransfer =0;
int messageLength;
sprintf(userCommand, "GET %s", file1);
messageLength = write(clientSocket,userCommand,strlen(userCommand));
if(messageLength <0){
perror("Error sending data to server in RETR");
return 0;
}
FILE *fp;
fp = fopen(file2, "w");
if(fp==NULL){
printf("%s Can not be created\n", file2);
return 0;
}
printf("Writing to file %s\n", file2);
while(!endOfTransfer){
messageLength = read(clientSocket, buffer, strlen(buffer)-1);
if(messageLength == -1){
perror("GET: Error in read() ");
break;
}
//puts(buffer);
printf("Buffer is %s with len %d\n", buffer, strlen(buffer));
tempString = strdup(buffer);
messageHead = atoi(strtok(tempString, " "));
messageContent = strtok(NULL, " ");
if(messageHead == 0 && strlen(messageContent)==0){ //End of file transfer
endOfTransfer = 1;
break;
}
fwrite(messageContent, sizeof(char), sizeof(messageContent), fp);
memset(buffer,0,sizeof(buffer));
printf("Buffer is %s with len %d\n", buffer, strlen(buffer));
}
fclose(fp);
return 1;
}
While running it, I am always getting the error "GET: Error in read() : Bad address". If I remove the statement
memset(buffer,0,sizeof(buffer));
I am getting a segmentation fault. I am assuming that the error has something to do with the string buffer being empty from the second iteration.
Any help to solve this will be highly appreciated.