Re: [AD] bugfix for files > 2GB under unix

[ Thread Index | Date Index | More lists.liballeg.org/allegro-developers Archives ]


On Mon, 2006-05-15 at 18:13 +0200, Elias Pschernig wrote:
> The attached patch allows the unix port to see files > 2GB - currently,
> all such files are silently ignored.
> 
> The size is not returned correctly simply because 32-bit datatypes are
> used - I'd like to update those as well, but keeping in mind binary
> compatibility, maybe better to do so only for 4.3. For a video player,
> currently there would be no way to play e.g. any DVDs since the files
> are usually > 2GB. The patch fixes that.
> 

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.

-- 
Elias Pschernig
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: include/allegro/file.h
===================================================================
--- include/allegro/file.h	(revision 5800)
+++ include/allegro/file.h	(working copy)
@@ -40,6 +40,7 @@
 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 +56,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"


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