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);
 


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/