Page 1 of 1

Using fseek with SEEK_CUR correctly

Posted: Fri Mar 11, 2016 11:06 pm
by ~
Image >> Watch the text recording for this program << Image

I have a file I want to append data to and I have used the following line to try to move right before EOF (but I suspect that it isn't necessary, I might make a simple test and post back):

Code: Select all

fseek(file, -1, SEEK_CUR);

Is that line correct or is it unnecessary when appending?


Here's the rest of the code and the full program (create_big_file.c) is at the start of the post, on the link surrounded by two Floppy-alike images:

Code: Select all


//Open appending to continue expanding file:
///
 fHandle=fopen(creatFileName, "ab+");


//We opened the file for appending, so try to move
//1 byte right before EOF:
///
 fseek(file, -1, SEEK_CUR);   //Move before EOF...




Full code:

Code: Select all

#include <stdio.h>

//NOTE: These two libraries seem to need to be together
//      to avoid an error message that says:
//
//      "warning: incompatible implicit declaration of built-in
//                function 'memset'":
///
 #include <stdlib.h>
 #include <string.h>


//This is a macro to easily access the first command line
//as the file name the program should use as a big file
//to create:
///
 #define creatFileName   argv[1]
 #define sectors512Count argv[2]


//(bytes_per_sect*sects)-zero_addressing
//
//for completing aligned/full file bytes
///
 #define creatFileSize____512MB          (512*1048576)-1
 #define creatFileSize____20GB0          39070080
 #define creatFileSize____875GBytes      939524096000
 #define creatFileSize____8754ksects     229376000
 #define creatFileSize____875GB512sects  1835008000



int main(int argc, char *argv[])
{
 //Here we just declare the variables
 //to handle the simple big file to create:
 ///
  void *buff;
  FILE *fHandle;
  const char *fName = "hard_disk.img";
  long int numsects = creatFileSize____512MB;


 if(argc<3)
 {
  printf("ERROR: Please specify a file name and a number of 512-byte sectors");
  printf("\r\n");
  return;
 }


 //Let's open (and create or overwrite)
 //the specified file name:
 ///
//if(!fHandle=fopen(creatFileName, "wb+"))  //Create new file...
  if(!fHandle=fopen(creatFileName, "ab+"))  //Append, continue expanding file...
  {
   printf("ERROR: Couldn't open %s\r\n", creatFileName);
   return -1;
  }


  if(!(abs(numsects=atol(sectors512Count))))
  {
   printf("ERROR: Sector count (%ld) must be greater than 0\r\n", numsects);
   return -2;
  }


 //We opened the file for appending, so try to move
 //1 byte right before EOF.
 //
 //These lines are unnecessary since the pointer
 //will be set at the end of file on the first
 //fwrite (in this case) or fread
 //(see http://f.osdev.org/viewtopic.php?f=13&p=258018#p258018)
 ///
//fseek(file, -1, SEEK_CUR);   //Move before EOF...
//fseek(file, 0,  SEEK_SET);   //Move to start... optional...


 //Reserve and clear a 512-byte buffer:
 ///
  buff=malloc(512);
  memset(
         buff,   //Buffer to zero out
         0,      //(int)(unsigned char) value to write (0 in this case)
         512     //Number of bytes to write
        );


 //Write as many 512-byte buffers as the requested
 //size in 512-byte sectors:
 ///
  do
  {
   fwrite(buff, 1, 512, fHandle);
  }
  while(--numsects);


 free(buff);
 fclose(fHandle);

 return 0;
}

Re: Using fseek with SEEK_SET correctly

Posted: Fri Mar 11, 2016 11:48 pm
by FallenAvatar
Without spending 30mins+ reading a spec (and without any useful info from you, and no I won't click your useless link), I would say your use of fseek in this case is UB at worst, or off-by-one in the best case. (Or, for simple people, its unnecessary/wrong)

- Monk

Edit: Went back and clicked your link, lost an entire core to your crap @$$ replay code. Yea, not happening again...

Re: Using fseek with SEEK_CUR correctly

Posted: Sat Mar 12, 2016 12:48 am
by Solar
Two misconceptions here.

One, EOF is not a value within the file that you'd need to take into account. It is a concept. The last data in the file is the last data (byte) in the file. If you fseek( file, 0, SEEK_END ), you are after that last data, not after EOF.

Two, opening a file in append mode will reposition the file pointer to EOF for every write operation. So your fseek() is pointless anyway because the fwrite() call will reposition to end-of-file anyway.

Oh, and your recorder tool... we've spoken about this. It doesn't add anything. I would have preferred a full-page listing; the buttons and fields and everything just got into the way.

Watching somebody else type in real time is like watching grass grow. Especially when there's no way to speed up. And if I *had* a way to speed up, I'd just fast-forward to the end anyway.

Re: Using fseek with SEEK_CUR correctly

Posted: Sat Mar 12, 2016 1:09 am
by FallenAvatar
Solar wrote:EOF is not a value within the file that you'd need to take into account. It is a concept. The last data in the file is the last data (byte) in the file.
Correct, minus I assume a mistype (just correcting for people who find this in the future,) in that the EOF marker is not in the file, nor on the file system. It is 100% an OS determined marker and can (with lots of caveats) be replaced "at will" with anything the OS designer chooses. It is a nothing but a Magic Number that the c library understands/transmits.
Solar wrote:If you fseek( file, 0, SEEK_END ), you are after that last data, not after EOF.

Two, opening a file in append mode will reposition the file pointer to EOF for every write operation.
Where is that defined? (I believe you, just not sure if its CLib, POSIX, or something else.)
Solar wrote:So your fseek() is pointless anyway because the fwrite() call will reposition to end-of-file anyway.
Yep, agreed.
Solar wrote:Oh, and your recorder tool... we've spoken about this. It doesn't add anything. I would have preferred a full-page listing; the buttons and fields and everything just got into the way.

Watching somebody else type in real time is like watching grass grow. Especially when there's no way to speed up. And if I *had* a way to speed up, I'd just fast-forward to the end anyway.
Add in the fact that it was programmed by someone without a clue what they are doing and we've pretty much guaranteed it will die the death it deserves.

- Monk

Re: Using fseek with SEEK_CUR correctly

Posted: Sat Mar 12, 2016 1:44 am
by iansjack
http://pubs.opengroup.org/onlinepubs/00 ... fopen.html

+1 about the recording tool. We're not children who need picture books.

Re: Using fseek with SEEK_CUR correctly

Posted: Sat Mar 12, 2016 11:15 am
by ~
Solar wrote:Watching somebody else type in real time is like watching grass grow. Especially when there's no way to speed up. And if I *had* a way to speed up, I'd just fast-forward to the end anyway.
It has "Fast forward". You can select the entries from the directory tree and drag it around. It's all dynamically added (you could as well modify the code, add directory tree entries and post it back to collaborate or fix).

At least it's a good way to make things easier to understand (it shows both the code and the end result), and it's more aimed at beginners. I hope it shows its full value when dealing with the hundreds of examples and Megabytes of kernel code or other complex projects, so that (mostly) beginners can see an increase in quality and understand even what is the first thing that runs in a program.
iansjack wrote:http://pubs.opengroup.org/onlinepubs/009695399/functions/fopen.html

+1 about the recording tool. We're not children who need picture books.
I guess it's more aimed at newcomers. I also need to learn in such a fine-grained way. I've also been an absolute newbie and I know that it can help many people.

What's key here is basing giving and asking for help in fully runnable programs, asking for the problematic lines and pointing to both the whole code and the text recording.

I guess I will keep converting regular tutorials, code, examples, forum posts, books and wiki pages to this additional format for the people who wants and truly needs to see how to start about such a complex task as a vital need and a vital format to learn.

It's still much better than just reading the whole code distribution or the whole book and having to unpack it logically without knowing what came first (which could as well be the simplest thing or actually the root, no matter if it's in the middle of the whole content instead of the very start of the code).

Re: Using fseek with SEEK_CUR correctly

Posted: Sat Mar 12, 2016 2:16 pm
by onlyonemac
~ wrote:It's still much better than just reading the whole code distribution or the whole book and having to unpack it logically without knowing what came first (which could as well be the simplest thing or actually the root, no matter if it's in the middle of the whole content instead of the very start of the code).
That's what tutorials are for: they say "add this bit first" or "you need to have xxx before you can add yyy", and they explain why things have to be written in the order that they're written. You can also get similar information from a VCS log. Watching the code being typed out character-by-character is excessive, when code is written in logical blocks (subroutines, files, or even just a group of lines) and all that really matters is "this block came before that block" or "in order to support the new functionality added by that block, these blocks needed to be changed like this", and your VCS log shows "added functionality to do xxx" and someone examining the VCS history can see what was changed in order to add the functionality to do xxx.

Re: Using fseek with SEEK_CUR correctly

Posted: Sat Mar 12, 2016 2:27 pm
by ~
onlyonemac wrote:
~ wrote:It's still much better than just reading the whole code distribution or the whole book and having to unpack it logically without knowing what came first (which could as well be the simplest thing or actually the root, no matter if it's in the middle of the whole content instead of the very start of the code).
That's what tutorials are for: they say "add this bit first" or "you need to have xxx before you can add yyy", and they explain why things have to be written in the order that they're written. You can also get similar information from a VCS log. Watching the code being typed out character-by-character is excessive, when code is written in logical blocks (subroutines, files, or even just a group of lines) and all that really matters is "this block came before that block" or "in order to support the new functionality added by that block, these blocks needed to be changed like this", and your VCS log shows "added functionality to do xxx" and someone examining the VCS history can see what was changed in order to add the functionality to do xxx.
I will take that into account; VCS logs and other stuff (like diffs) can be added here too.

It's not so much char by char but event by event. It will be useful:

- When drawing when I add an image/animation editor (to show the sequence and being able to save any intermediate drawing point).

- For demonstrating without a doubt that the code is fully original against an ownership contest...

- ...And when I add real-time participation (read and/or write) over the Internet.

What is good about watching the full typing style and sequence is that, as you can see, explanations and understanding of the problem becomes so trivial that there's even time to discuss peripheral talk...