Re: [AD] bugfix for files > 2GB under unix |
[ Thread Index |
Date Index
| More lists.liballeg.org/allegro-developers Archives
]
On Tue, 2006-05-16 at 14:56 +0200, Elias Pschernig wrote:
>
> Actually, providing wrong file sizes looks really broken, so here's now
> a proper patch. To work around binary compatibility, I sneaked in an
> extra size field into an internal struct, and provided an accessor
> function. For file size, there's simply "uint64_t file_size_ex" now.
Here is the complete patch, ready to be applied. Everything is
documented, file_size is deprecated, the 32-bit "size" field of al_ffblk
is no longer documented, and all examples/tools are updated accordingly.
So, Allegro 4.2.1 will be able to list all files up to about 10
ExaByte :)
--
Elias Pschernig
Index: src/config.c
===================================================================
--- src/config.c (revision 5800)
+++ src/config.c (working copy)
@@ -451,7 +451,7 @@
static void load_config_file(CONFIG **config, AL_CONST char *filename, AL_CONST char *savefile)
{
char *tmp, *tmp2;
- int length;
+ uint64_t length;
if (*config) {
destroy_config(*config);
@@ -464,7 +464,7 @@
return;
}
- length = file_size(filename);
+ length = file_size_ex(filename);
if (length > 0) {
PACKFILE *f = pack_fopen(filename, F_READ);
Index: src/unix/ufile.c
===================================================================
--- src/unix/ufile.c (revision 5800)
+++ src/unix/ufile.c (working copy)
@@ -18,11 +18,16 @@
#include <stdio.h>
#include <string.h>
-#include <sys/stat.h>
#include "allegro.h"
#include "allegro/internal/aintern.h"
+#ifdef HAVE_SYS_STAT_H
+#ifdef HAVE_STAT64
+#define __USE_LARGEFILE64
+#endif
+#include <sys/stat.h>
+#endif
#ifdef HAVE_DIRENT_H
#include <sys/types.h>
@@ -53,6 +58,9 @@
#endif
#endif
+#ifdef HAVE_STAT64
+#define stat stat64
+#endif
/* _al_file_isok:
@@ -300,6 +308,7 @@
char dirname[FF_MAXPATHLEN];
char pattern[FF_MAXPATHLEN];
int attrib;
+ uint64_t size;
};
@@ -315,10 +324,18 @@
char tmp[1024];
char *p;
+ /* allocate ff_data structure */
+ ff_data = _AL_MALLOC(sizeof(struct FF_DATA));
+ if (!ff_data) {
+ *allegro_errno = ENOMEM;
+ return -1;
+ }
+
+ memset(ff_data, 0, sizeof *ff_data);
+ info->ff_data = (void *) ff_data;
+
/* if the pattern contains no wildcard, we use stat() */
if (!ustrpbrk(pattern, uconvert("?*", U_ASCII, tmp, U_CURRENT, sizeof(tmp)))) {
- info->ff_data = NULL;
-
/* start the search */
errno = *allegro_errno = 0;
@@ -330,28 +347,19 @@
if ((actual_attrib & ~attrib) == 0) {
info->attrib = actual_attrib;
info->time = s.st_mtime;
- info->size = s.st_size;
+ info->size = s.st_size; /* overflows at 2GB */
+ ff_data->size = s.st_size;
ustrzcpy(info->name, sizeof(info->name), get_filename(pattern));
return 0;
}
}
+ _AL_FREE(ff_data);
+ info->ff_data = NULL;
*allegro_errno = (errno ? errno : ENOENT);
return -1;
}
- /* allocate ff_data structure */
- ff_data = _AL_MALLOC(sizeof(struct FF_DATA));
-
- if (!ff_data) {
- *allegro_errno = ENOMEM;
- return -1;
- }
-
- /* attach it to the info structure */
- info->ff_data = (void *) ff_data;
-
- /* initialize it */
ff_data->attrib = attrib;
do_uconvert(pattern, U_CURRENT, ff_data->dirname, U_UTF8, sizeof(ff_data->dirname));
@@ -400,8 +408,10 @@
struct stat s;
struct FF_DATA *ff_data = (struct FF_DATA *) info->ff_data;
+ ASSERT(ff_data);
+
/* if the pattern contained no wildcard */
- if (!ff_data)
+ if (!ff_data->dir)
return -1;
while (TRUE) {
@@ -441,7 +451,8 @@
info->attrib = attrib;
info->time = s.st_mtime;
- info->size = s.st_size;
+ info->size = s.st_size; /* overflows at 2GB */
+ ff_data->size = s.st_size;
do_uconvert(tempname, U_UTF8, info->name, U_CURRENT, sizeof(info->name));
Index: src/file.c
===================================================================
--- src/file.c (revision 5800)
+++ src/file.c (working copy)
@@ -725,12 +725,12 @@
-/* file_size:
+/* file_size_ex:
* Returns the size of a file, in bytes.
* If the file does not exist or an error occurs, it will return zero
* and store the system error code in errno.
*/
-long file_size(AL_CONST char *filename)
+uint64_t file_size_ex(AL_CONST char *filename)
{
ASSERT(filename);
if (ustrchr(filename, '#')) {
@@ -752,6 +752,13 @@
+long file_size(AL_CONST char *filename)
+{
+ return file_size_ex(filename);
+}
+
+
+
/* file_time:
* Returns a file time-stamp.
* If the file does not exist or an error occurs, it will return zero
Index: docs/src/api._tx
===================================================================
--- docs/src/api._tx (revision 5800)
+++ docs/src/api._tx (working copy)
@@ -185,6 +185,8 @@
<li>
fhypot (fixhypot).
<li>
+ file_size (file_size_ex)
+<li>
file_select (file_select_ex, passing the two constants OLD_FILESEL_WIDTH
and OLD_FILESEL_HEIGHT if you want the file selector to be displayed with
the dimensions of the old file selector).
Index: docs/src/allegro._tx
===================================================================
--- docs/src/allegro._tx (revision 5800)
+++ docs/src/allegro._tx (working copy)
@@ -749,12 +749,11 @@
to obtain/use this structure.
@@struct @al_ffblk
-@domain.hid al_findfirst
+@xref al_findfirst, al_ffblk_get_size
@shortdesc Cross platform structure storing file information.
<codeblock>
int attrib; - actual attributes of the file found
time_t time; - modification time of file
- long size; - size of file
char name[512]; - name of file
<endblock>
Read the description of al_findfirst for a description on how to
@@ -10262,7 +10261,7 @@
name, it's out of date.
@@int @file_exists(const char *filename, int attrib, int *aret);
-@domain.hid exists, file_size, file_time
+@xref exists, file_size_ex, file_time
@shortdesc Tells if a file exists.
Checks whether a file matching the given name and attributes (see
beginning of this chapter) exists. If `aret' is not NULL, it will be set
@@ -10276,7 +10275,7 @@
specified attributes mask it out.
@@int @exists(const char *filename);
-@domain.hid file_exists, file_size, file_time
+@xref file_exists, file_size_ex, file_time
@shortdesc Shortcut version of file_exists() for normal files.
Shortcut version of file_exists(), which checks for normal files, which
may have the archive or read-only bits set, but are not hidden,
@@ -10284,7 +10283,7 @@
@retval
Returns non-zero if the file exists, or zero if it doesn't.
-@domain.hid @file_size(const char *filename);
+@@uint64_t @file_size_ex(const char *filename);
@xref file_exists, file_time
@eref expackf
@shortdesc Returns the size of a file in bytes.
@@ -10293,7 +10292,7 @@
errno.
@@time_t @file_time(const char *filename);
-@domain.hid file_exists, file_size
+@xref file_exists, file_size_ex
@shortdesc Returns the modification time of a file.
Returns the modification time (number of seconds since 00:00:00 GMT
1/1/1970) of a file. If the file does not exist or an error occurs, it
@@ -10343,7 +10342,7 @@
number of times callback() was called and returned 0.
@@int @al_findfirst(const char *pattern, struct al_ffblk *info, int attrib);
-@domain.hid al_findnext, al_findclose
+@xref al_findnext, al_findclose, al_ffblk_get_size
@shortdesc Low-level function for searching files.
Low-level function for searching files. This function finds the first
file which matches the given wildcard specification and file attributes
@@ -10355,7 +10354,6 @@
{
int attrib; - actual attributes of the file found
time_t time; - modification time of file
- long size; - size of file
char name[512]; - name of file
};
<endblock>
@@ -10399,6 +10397,11 @@
call this on all successfully opened searches to avoid memory leaks in
your program.
+@@uint64_t @al_ffblk_get_size(struct al_ffblk *info);
+@xref al_findfirst, al_findnext, al_ffblk
+@shortdesc Get size of file returned by al_findfirst/al_findnext.
+ This returns the size of the file returned by al_findfirst or al_findnext.
+
@\int @find_allegro_resource(char *dest, const char *resource,
@\ const char *ext, const char *datafile,
@\ const char *objectname, const char *envvar,
@@ -15990,7 +15993,7 @@
@@Example @expackf
@xref ASSERT, BITMAP, END_OF_MAIN, PACKFILE, PACKFILE_VTABLE, SCREEN_H
@xref SCREEN_W, alert, allegro_error, allegro_init, allegro_message, blit
-@domain.hid clear_bitmap, destroy_bitmap, file_size, font, install_keyboard
+@xref clear_bitmap, destroy_bitmap, file_size_ex, font, install_keyboard
@xref key, load_bmp_pf, load_pcx, load_pcx_pf, load_tga_pf, pack_fclose
@xref pack_fopen, pack_fopen_vtable, pack_fread, pack_fseek, readkey
@xref save_bmp_pf, save_tga_pf, screen, set_color_depth, set_gfx_mode
Index: tools/pat2dat.c
===================================================================
--- tools/pat2dat.c (revision 5800)
+++ tools/pat2dat.c (working copy)
@@ -545,7 +545,7 @@
static DATAFILE *grab_patch(int type, AL_CONST char *filename, DATAFILE_PROPERTY **prop, int depth)
{
PACKFILE *f;
- long sz = file_size(filename);
+ int64_t sz = file_size_ex(filename);
char buf[256];
int inst, layer, sample, i;
int data_size, data_size_pos;
Index: tools/grabber.c
===================================================================
--- tools/grabber.c (revision 5800)
+++ tools/grabber.c (working copy)
@@ -2993,14 +2993,15 @@
char buf[256];
PACKFILE *f;
char *help_text, *last, *s;
- int size, i, j, cr;
+ int i, j, cr;
+ int64_t size;
CHECK_MENU_HOOK("Help", DATEDIT_MENU_HELP);
get_executable_name(buf, sizeof(buf));
strcpy(get_filename(buf), "grabber.txt");
- size = file_size(buf);
+ size = file_size_ex(buf);
if (size <= 0) {
alert("Error reading grabber.txt", NULL, NULL, "Oh dear", NULL, 13, 0);
return D_REDRAW;
Index: tools/datedit.c
===================================================================
--- tools/datedit.c (revision 5800)
+++ tools/datedit.c (working copy)
@@ -197,7 +197,7 @@
static DATAFILE *grab_binary(int type, AL_CONST char *filename, DATAFILE_PROPERTY **prop, int depth)
{
void *mem;
- long sz = file_size(filename);
+ int64_t sz = file_size_ex(filename);
PACKFILE *f;
if (sz <= 0)
@@ -1224,7 +1224,7 @@
delete_file(backup_name);
if (options->verbose) {
- int file_filesize = file_size(pretty_name);
+ uint64_t file_filesize = file_size_ex(pretty_name);
datedit_msg("%-28s%7d bytes into %-7d (%d%%)", "- GLOBAL COMPRESSION -",
file_datasize, file_filesize, percent(file_datasize, file_filesize));
}
Index: tools/pack.c
===================================================================
--- tools/pack.c (revision 5800)
+++ tools/pack.c (working copy)
@@ -83,7 +83,7 @@
return 1;
}
- s1 = file_size(f1);
+ s1 = file_size_ex(f1);
in = pack_fopen(f1, m1);
if (!in) {
@@ -115,7 +115,7 @@
return 1;
}
- s2 = file_size(f2);
+ s2 = file_size_ex(f2);
if (s1 == 0)
printf("\nInput size: %ld\nOutput size: %ld\n", s1, s2);
else
Index: tests/filetest.c
===================================================================
--- tests/filetest.c (revision 5800)
+++ tests/filetest.c (working copy)
@@ -290,7 +290,7 @@
/* put_size:
* Helper function for displaying the file size.
*/
-static void put_size(char *buffer, long size)
+static void put_size(char *buffer, uint64_t size)
{
char tmp1[128];
@@ -354,10 +354,10 @@
#ifdef USE_FINDFIRST
put_time(flist->name[c] + TIME_OFFSET, info->time);
- put_size(flist->name[c] + SIZE_OFFSET, info->size);
+ put_size(flist->name[c] + SIZE_OFFSET, al_ffblk_get_size(info));
#else
put_time(flist->name[c] + TIME_OFFSET, file_time(str));
- put_size(flist->name[c] + SIZE_OFFSET, file_size(str));
+ put_size(flist->name[c] + SIZE_OFFSET, file_size_ex(str));
#endif
ustrcpy(flist->name[c] + NAME_OFFSET, s);
Index: include/allegro/alcompat.h
===================================================================
--- include/allegro/alcompat.h (revision 5800)
+++ include/allegro/alcompat.h (working copy)
@@ -146,6 +146,8 @@
/* the old (and broken!) file enumeration function */
AL_FUNC_DEPRECATED(int, for_each_file, (AL_CONST char *name, int attrib, AL_METHOD(void, callback, (AL_CONST char *filename, int attrib, int param)), int param));
+/* long is 32-bit only on some systems, and we want to list DVDs! */
+AL_FUNC_DEPRECATED(long, file_size, (AL_CONST char *filename));
/* the old state-based textout functions */
Index: include/allegro/file.h
===================================================================
--- include/allegro/file.h (revision 5800)
+++ include/allegro/file.h (working copy)
@@ -39,7 +39,7 @@
AL_FUNC(void, put_backslash, (char *filename));
AL_FUNC(int, file_exists, (AL_CONST char *filename, int attrib, int *aret));
AL_FUNC(int, exists, (AL_CONST char *filename));
-AL_FUNC(long, file_size, (AL_CONST char *filename));
+AL_FUNC(uint64_t, file_size_ex, (AL_CONST char *filename));
AL_FUNC(time_t, file_time, (AL_CONST char *filename));
AL_FUNC(int, delete_file, (AL_CONST char *filename));
AL_FUNC(int, for_each_file_ex, (AL_CONST char *name, int in_attrib, int out_attrib, AL_METHOD(int, callback, (AL_CONST char *filename, int attrib, void *param)), void *param));
@@ -55,6 +55,8 @@
void *ff_data; /* private hook */
};
+AL_FUNC(uint64_t, al_ffblk_get_size, (struct al_ffblk *info));
+
AL_FUNC(int, al_findfirst, (AL_CONST char *pattern, struct al_ffblk *info, int attrib));
AL_FUNC(int, al_findnext, (struct al_ffblk *info));
AL_FUNC(void, al_findclose, (struct al_ffblk *info));
Index: configure.in
===================================================================
--- configure.in (revision 5800)
+++ configure.in (working copy)
@@ -713,7 +713,7 @@
AC_STRUCT_TM
AC_TYPE_SIGNAL
-AC_CHECK_FUNCS(mmap mprotect memcmp mkstemp stricmp strlwr strupr vprintf)
+AC_CHECK_FUNCS(mmap mprotect memcmp mkstemp stricmp strlwr strupr vprintf stat64)
dnl Tweak header files for library build
CFLAGS="$CFLAGS -DALLEGRO_LIB_BUILD"
Index: examples/expackf.c
===================================================================
--- examples/expackf.c (revision 5800)
+++ examples/expackf.c (working copy)
@@ -243,11 +243,11 @@
MEMREAD_INFO memread_info;
BITMAP *bmp, *bmp2;
unsigned char *block;
- int l1, l2;
+ int64_t l1, l2;
PACKFILE *f1, *f2;
- l1 = file_size("allegro.pcx");
- l2 = file_size("mysha.pcx");
+ l1 = file_size_ex("allegro.pcx");
+ l2 = file_size_ex("mysha.pcx");
block = malloc(l1 + l2);