Jump to content
Search In
  • More options...
Find results that contain...
Find results in...
Sign in to follow this  
Quasar

Interesting tidbit I found

Recommended Posts

CERT says Thou-Shalt-Not use fseek/ftell to determine file sizes!

https://www.securecoding.cert.org/confluence/display/seccode/FIO19-C.+Do+not+use+fseek%28%29+and+ftell%28%29+to+compute+the+size+of+a+file

Turns out ISO doesn't require binary streams to support SEEK_END, and of course most people already know fseek is wonky on text streams. So that leaves nowhere that it's both safe AND portable to do this >_>

Share this post


Link to post

Apparently this is what may be causing the read/write issues with savegames for Doom64ex. Problem is this may affect other source ports as well such as Chocolate Doom.

Share this post


Link to post

CERT recommends fstat, which is really slow compared to fseek/ftell where they actually work.

Share this post


Link to post

Well, unless you have to somehow find out the size of several thousands files by opening them first, does this really matter? I guess it also has to do with how a particular OS/library actually populates the fstat object. In some development environments it's easy to get info about a file that you *didn't* open, or even receive a full directory listing without much effort, while in others you have to jump through hoops.

Still, it's a method we've all have used :-/

Share this post


Link to post

Their compliant solution sucks. You shouldn't have to use the kernel facilities like open() for something as basic as this, the whole point of fopen(), fread() etc is to abstract away those low-level facilities.

Share this post


Link to post

This is a recommendation I will happily ignore unless someone points me to a system where it really does not work.

Share this post


Link to post
Quasar said:

CERT recommends fstat, which is really slow compared to fseek/ftell where they actually work.

Really? On my system, at least according to strace, calling fseek calls fstat (as well as precaching a bit of the file.) So fseek must be at least as slow as fstat...

$ strace -o trace ./fseek ~/doom/W/epic2/epic2.wad

/home/rjy/doom/W/epic2/epic2.wad: 37243712

$ sed -ne '/open.*epic2.wad/,$p' trace

open("/home/rjy/doom/W/epic2/epic2.wad", O_RDONLY) = 3
fstat64(3, {st_mode=S_IFREG|0644, st_size=37243712, ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7755000
fstat64(3, {st_mode=S_IFREG|0644, st_size=37243712, ...}) = 0
_llseek(3, 37240832, [37240832], SEEK_SET) = 0
read(3, " s,\2\0\20\0\0SFLOOR05 \203,\2\0\20\0\0SFLOOR06"..., 2880) = 2880
fstat64(1, {st_mode=S_IFCHR|0620, st_rdev=makedev(136, 2), ...}) = 0
mmap2(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0xb7754000
write(1, "/home/rjy/doom/W/epic2/epic2.wad"..., 43) = 43
close(3)                                = 0
munmap(0xb7755000, 4096)                = 0
exit_group(0)                           = ?
fseek.c
#include <stdlib.h>
#include <stdio.h>

int main(int argc, char **argv)
{
  while (++argv, --argc)
  { 
    char *name = *argv;
    FILE *F = fopen(name, "rb");
    size_t length;
    
    fseek(F, 0, SEEK_END);
    length = ftell(F);

    printf("%s: %lu\n", name, length);
    
    fclose(F);
  } 
    
  return EXIT_SUCCESS;
} 
I'm too stupid/lazy to benchmark it properly :-P

Share this post


Link to post

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
Sign in to follow this  
×