Unexpected behaviour of lseek - c

I am using lseek just to find the size of a file and lseek returns less bytes than the file's actual size. I think the code is right and I can't explain why that happens.
When i ran the program for the first time it worked well. Then I added some data to the file so it changed its size. Since then, when I run the program again with the new file, the result is always the size of the old file.
Any help appreciated!
int main(int argc,char* argv[]){
int out_file_size=0;
int fd_prognameout;
fd_prognameout=open(argv[1],O_RDWR | O_CREAT,00700);
if(fd_prognameout == -1){
perror("Error:");
return(0);
}
lseek(fd_prognameout,0,SEEK_SET);
out_file_size = lseek(fd_prognameout,0,SEEK_END);
lseek(fd_prognameout,0,SEEK_SET);
printf("The size of out file is: %d\n",out_file_size);
close(fd_prognameout);
return(0);
}

First, lets change these lines
lseek(fd_prognameout,0,SEEK_SET);
out_file_size = lseek(fd_prognameout,0,SEEK_END);
lseek(fd_prognameout,0,SEEK_SET);
to
//get the current file position
off_t current_pos = lseek(fd_prognameout,0,SEEK_CUR);
//get the last position (size of file)
off_t out_file_size = lseek(fd_prognameout,0,SEEK_END);
//reset to the previous position
lseek(fd_prognameout,current_pos,SEEK_SET);
Now to your problem. Modifications to a file might not be immediately visible (due to caching/buffering by the kernel).
After modifying a file, either run the command sync or call in your code the functions fsync() or fdatasync().

Related

Replacing bytes at current offset in c

I'm currently developing a program that mimics UNIX file system. I've prepared my disk as file (1 MB) got all data blocks inside it. Now what I'm doing is implementing some simple commands like mkdir, ls etc. In order to work with those commands, I need to read specific offset(no problem with that) and write the modified blocks to specific location.
Simply my goal is:
SIIIDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD (Current Disk)
I wan't to change three blocks with AAA after 16.byte so it will be like:
SIIIDDDDDDDDDDDDAAADDDDDDDDDDDDDDDDDDDDDDDDDDDDDDD (Modified Disk)
I'm not going to provide all of my implementation here I just want to have some ideas about it how can I implement it without buffering all the 1 MB data in my program. In short I know locations of my data blocks so I just want to replace that part of my file not whole file. Can't I simply do this with file stream functions ?
Another example:
fseek(from_disk,superblock.i_node_bit_map_starting_addr , SEEK_SET); //seek to known offset.
read_bit_map(&from_disk); // I can read at specific location without problem
... manipulate bit map ...
fseek(to_disk,superblock.i_node_bit_map_starting_addr , SEEK_SET); //seek to known offset.
write_bit_map(&to_disk); //Write back the data.
//This will destroy the current data of file. (Tried with w+, a modes.)
Note: Not provided in example but I have two file pointers both writing and reading and I'm aware I need to close one before opening another.
I think you are looking for the r+ (potentially rb+ mode). Here is a complete example, afterwards you can run grep -n hello data.txt to verify for yourself the result. You can run it with make prog && ./prog.
#include <stdio.h>
#include <unistd.h>
#include <string.h>
int main(int argc, char const *argv[])
{
FILE *file;
file = fopen("data.txt", "w+");
char dummy_data[] = "This is stackoverflow.com\n";
int dummy_data_length = strlen(dummy_data);
for (int i = 0; i < 1000; ++i)
fwrite(dummy_data, dummy_data_length, 1, file);
fclose(file);
file = fopen("data.txt", "r+");
fseek(file, 500, SEEK_CUR);
fwrite("hello", 5, 1, file);
fclose(file);
return 0;
}

C - Modifying a file

I have a solution here that supposedly opens a file and changes the last character of it. I don't quite understand how this works. Could you please explain?
void readlast()
{
int handle = open("./file.txt", O_RDWR|O_CREAT, S_IRUSR|S_IWUSR);
if (handle < 0)
{
return;
}
Okay, this part opens the file and if it doesn't work, returns.
First question: Why is a file opening an integer (int handle)? What is being stored in it?
char c='N';
lseek(handle, -2*sizeof(c), SEEK_END);
lseek apparently changes the location of a reader. So I guess this sets the reader to the end of a file(SEEK_END). But why do we need an offset of -2*sizeof(c) if we just want to write one character?
write(handle, &c, sizeof(c));
close(handle);
}
I do understand this last part.
Thank you!
Normally a file descriptor is returned by open() and it is an integer. 0 and 1 are customarily standard I/O.
File size - 2 [octets] is the offset of last character/byte.

Open image file as binary, store image as string of bytes, save the image - possible in plain C?

I would like to read an image, lets say, picture.png in C. I know I can open it in binary mode, and then read - it's pretty simple.
But I need something more: I would like to be able to read the image once, store it in my code, for example, in *.h file, as 'string of bytes', for example:
unsigned char image[] = "0x87 0x45 0x56 ... ";
and then, be able to just do:
delete physical file I read from disk,
save image into file - it will create my file once again,
EVEN if I removed image from disk (deleted physical file picture.png I read earlier) I will still be able to create an image on disk, simply by writing my image array into file using binary mode. Is that possible in pure C? If so, how can I do this?
There's even a special format for this task, called XPM and a library to manipulate these files. But remember due to its nature it's suitable only for relatively small images. But yes, it was used for years in X Window System to provide icons. Well, those old good days icons were 16x16 pixels wide and contained no more than 256 colors :)
Of course it's possible, but it's a bit unclear what you're after.
There are stand-alone programs that convert binary data to C source code, you don't need to implement that. But doing it that way of course means that the image becomes a static part of your program's executable.
If you want it to be more dynamic, like specifying the filename to your program when it's running, then the whole thing about converting to C source code becomes moot; your program is already compiled. C programs can't add to their own source at run-time.
UPDATE If all you want to do is load a file, hold it in memory and then write it back out, all in the same run of your program, that's pretty trivial.
You'd use fopen() to open the file, fseek() to go to the end, ftell() to read the size of the file. Then rewind() it to the start, malloc() a suitable buffer, fread() the file's contents into the buffer and fclose() the file. Later, fopen() a new output file, and fwrite() the buffer into that before using fclose() to close the file. Then you're done. You can do it again, as many times as you like. It can be an image, a program, a document or any other kind of file, it doesn't matter.
pic2h.c :
#include <stdio.h>
int main(int argc, char *argv[]){
if(argc != 3){
fprintf(stderr, "Usage >pic2h image.png image.h\n");
return -1;
}
FILE *fi = fopen(argv[1], "rb");
FILE *fo = fopen(argv[2], "w");
int ch, count = 0;
fprintf(fo, "extern unsigned char image[];\n");
fprintf(fo, "unsigned char image[] =");
while(EOF!=(ch=fgetc(fi))){
if(count == 0)
fprintf(fo, "\n\"");
fprintf(fo, "\\x%02X", ch);
if(++count==24){
count = 0;
fprintf(fo, "\"");
}
}
if(count){
fprintf(fo, "\"");
}
fprintf(fo, ";\n");
fclose(fo);
fclose(fi);
return 0;
}
resave.c :
#include <stdio.h>
#include "image.h"
int main(int argc, char *argv[]){
if(argc != 2){
fprintf(stderr, "Usage >resave image.png\n");
return 0;
}
size_t size = sizeof(image)-1;
FILE *fo = fopen(argv[1], "wb");
fwrite(image, size, 1, fo);
fclose(fo);
return 0;
}

Printing to a file while conducting n simulations for a program (in C)

I am conducting n simulations using a program and albeit everything being correct, there is only one mistake which I am able to see in the output files.
I am printing the outputs of the program to a csv file.
I check the file before I print to it to get it's size which if it is 0, I print the headers. Here is the function which does the same:
void Data_Output(FILE *fp, int node_num, int agg_num, int cnode, int sysdelay, int bwdth_reqt)
{
struct stat buf;
int fd = fileno(fp);
fstat(fd, &buf);
//Debug Statement
fprintf(stderr,"%d-",buf.st_size);
if (!buf.st_size) {
// Writing Headers
fprintf(fp,"Tot_Nodes_Num,Agg_Nodes_Num,Central_Node_Num,Tot_System_Delay,Bandwidth_Reqt\n");
}
// Writing Data
fprintf(fp,"%d,%d,%d,%d,%d\n",node_num,agg_num,cnode,sysdelay,bwdth_reqt);
}
For 100 simulations, the output I get from the debug shows me:
0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-0-
What am I doing wrong? I suspect that the program stores everything in a buffer and only prints everything to the file after it is done with the simulations and the files are closed.
Note: I open and close the files only once during the whole program and not for each simulation.
You are correct. Stdio has it's own output buffering and fstat is only concerned with logical files. So the file writes do get delayed. Try putting fflush(fp); for the last line in your Data_Output function. I hope that helps.

Random writing order to output file?

I've written a program that writes information to a file. The output to the file is not in the order that I am expecting. I have a header line and three additional lines with numerical information. The header comes first following by the third, first, and second lines.
Note that the file is open in a mode, not a+. According to various sources, re-positioning operators like fseek() are suppose to be ignored. For a while I was actually getting the third line before the first line after that line was written. If the fseek() line is omitted, the third line actually is written before the header ..
If the fseek() function is left commented (regardless of being in a or a+ mode) the output is as shown in the picture below.
I wrote in a bit of code to see how the output should be written. The text in the file is certainly not what it should be ..
I attempted to use the fseek() function to find the position just before the EOF before each write but to no avail.
I have also noticed that if I use fflush(writeP) then I get the same effect that including the fseek() function would. The file is still out of order as shown, but the third line is no longer before the header line.
What am I missing?
void quickSortHelper(int* num, long startTime, long endTime, int size){
FILE *writeP = fopen(QUICKSORT_FILE, "a");
if(writeP == NULL){
fputs("Error opening file\n", stderr);
exit(1);
}
static int times = 0;
long deltaT; //change in time
if(size < STEPSIZE){//first time, write header to file
printf("Writing header!\n");
fprintf(writeP, " --- QUICKSORT ---\nCOUNT\tTIME\tMEDIAN\n");
}
deltaT = (clock() - startTime)/(CLOCKS_PER_SEC/1000);
//fflush(writeP);
fseek(writeP, -1, SEEK_END);
printf("Writing: %d\t%ld\t%d\n", size, deltaT, findMedian(num, size));
fprintf(writeP, "%d\t%ld\t%d\n", size, deltaT, findMedian(num, size));
if(++times == 3)
fclose(writeP);
return;
}
With the fseek() line commented, the output is:
You do not close writeP the first 3 times when function is called. So, the file is opened by several FILE handles which get closed on exit. The "a" works only for the same FILE handle or when data have reached the disk.
The problem comes from the fact that you open the same file on every function call, but only close it on the third call. I would suggest moving the file opening and closing logic out of that function, and passing the FILE * handle as an argument to the function; this would also avoid having to hard code the call number on which to close into that function.
So the place where you call the function would look something like this:
FILE *writeP = fopen(QUICKSORT_FILE, "w"); // "a" changed to "w"
if (!writeP) {
perror(QUICKSORT_FILE);
exit(1);
}
// perhaps write the header into the file here
for (int i = 0; i < 3; ++i) {
// do the quicksort
write_quicksort_results(writeP, …);
}
(void) fclose(writeP);

Resources