tsoding / ded

Dramatic EDitor
MIT License
579 stars 75 forks source link

file_size() gives crazy big values back #86

Closed PeriodGamingYT closed 1 year ago

PeriodGamingYT commented 1 year ago

./ded . Loading . bruh result 9223372036854775807 saved 0 bruh size 9223372036854775807 bruh cap 9223372036854775807 items 1 9223372036854775807 ded: src/common.c:109: read_entire_file: Assertion `sb->items != NULL && "Buy more RAM lol"' failed. Aborted (core dumped)

after some diagnosing, fseek(fp, 0, SEEK_END) is giving back some crazy weird values.

BillKek commented 1 year ago

9223372036854775807 is 7FFFFFFFFFFFFFFF. Probably it is magic number of error code.

PeriodGamingYT commented 1 year ago

7FFFFFFFFFFFFFFF is not a magic number. Rather (int) 0x7FFFFFFFFFFFFFFF returns -1. So, if(result < 0) needs to be if((int) result < 0). EDIT: This is because result is a long, it's unsigned by default. Why? I have no idea.

PeriodGamingYT commented 1 year ago

Though, this fix gives a different error, which is probably me not giving a proper directory. The error now is ERROR: Could not read file ./: Operation not permitted. It thinks its trying to read a file. Maybe there's an option for specifying a directory, or putting nothing at all makes it read a directory. Not too sure.

PeriodGamingYT commented 1 year ago

So, you have to press F3 without specifying a directory. That's what takes you to the file browser. I think with the file error, we should also say something like HELP: If you're trying to open a directory, specify a file inside that directory, then use F3 inside the program to get to the file manager..

BillKek commented 1 year ago

Rather (int) 0x7FFFFFFFFFFFFFFF returns -1. So, if(result < 0) needs to be if((int) result < 0).

No,no,no! Imagine that real file size is 5 GB. And (int32)filesize will be able to give < 0 !

eloj commented 1 year ago

I'd be interested to know the OPs OS/compiler/flags, because any platform or environment where long is unsigned by default is weird IMO.

So anyway, it'd probably be better to check errno explicitly, instead of trying to interpret the return value.

 static Errno file_size(FILE *file, size_t *size)
 {
+    errno = 0;
     long saved = ftell(file);
-    if (saved < 0) return errno;
+    if (errno) return errno;
     if (fseek(file, 0, SEEK_END) < 0) return errno;
     long result = ftell(file);
-    if (result < 0) return errno;
+    if (errno) return errno;
     if (fseek(file, saved, SEEK_SET) < 0) return errno;
     *size = (size_t) result;
     return 0;

Plus, saving and restoring the stream pointer would likely be better handled using fgetpos and fsetpos. Left as an exercise.

There's also the whole ftello/fseeko interface using off_t instead of long, sidestepping that issue. Then you'll want to -D _FILE_OFFSET_BITS=64. Unfortunately this is even less portable.

All that is to say, if for some reason you don't want to use an fstat-style call instead of this whole seeking business.

PeriodGamingYT commented 1 year ago

Using fstat is probably a better idea imo. Same thing using errno and not the return value of fseek.