I don't know why, but this bug never bit me in years, and became
extremely common with a patch I'm working on. The idea is that C object that persist across image save become dangling pointers when you load the image! This is fixed easily by *not* using C objects when it's not necessary. The patch provides backwards-compatibility functions because I'd like to apply it to stable-3.0 too, but I don't have much time to do the required testing now. Paolo 2008-03-26 Paolo Bonzini <[hidden email]> * kernel/VFS.st: Use new variants of stat/lstat that fill in a Smalltalk object. * libgst/cint.c: Add stat/lstat versions that return an object. * libgst/dict.inl: Move from/to off_t conversion here... * libgst/prims.def: ... from here. diff --git a/kernel/VFS.st b/kernel/VFS.st index 2b9a2e4..d31acf7 100644 --- a/kernel/VFS.st +++ b/kernel/VFS.st @@ -164,15 +164,15 @@ actually accessing or ``molding'''' the filesystem.'> ^subPath isNil ifTrue: [handler] ifFalse: [handler at: subPath] ] - lstatOn: fileName into: statStruct [ + lstatOn: fileName into: stat [ <category: 'private-C call-outs'> - <cCall: 'lstat' returning: #int args: #(#string #cObject)> + <cCall: 'lstat_obj' returning: #int args: #(#string #smalltalk)> ] - statOn: fileName into: statStruct [ + statOn: fileName into: stat [ <category: 'private-C call-outs'> - <cCall: 'stat' returning: #int args: #(#string #cObject)> + <cCall: 'stat_obj' returning: #int args: #(#string #smalltalk)> ] @@ -544,14 +544,14 @@ up being on disk when they are opened for the first time.'> "Answer the size of the file identified by the receiver" <category: 'accessing'> - ^self stat stSize value + ^self stat stSize ] mode [ "Answer the octal permissions for the file." <category: 'accessing'> - ^self stat stMode value bitAnd: 4095 + ^self stat stMode bitAnd: 4095 ] mode: mode [ @@ -566,7 +566,7 @@ up being on disk when they are opened for the first time.'> "Answer whether the file is a directory." <category: 'accessing'> - ^(self stat stMode value bitAnd: 61440) = 16384 + ^(self stat stMode bitAnd: 61440) = 16384 ] isSymbolicLink [ @@ -581,7 +581,7 @@ up being on disk when they are opened for the first time.'> "Answer the last access time of the file identified by the receiver" <category: 'accessing'> - ^self getDateAndTime: self stat stAtime value + ^self getDateAndTime: self stat stAtime ] lastChangeTime [ @@ -591,7 +591,7 @@ up being on disk when they are opened for the first time.'> file creation time." <category: 'accessing'> - ^self getDateAndTime: self stat stCtime value + ^self getDateAndTime: self stat stCtime ] creationTime [ @@ -601,7 +601,7 @@ up being on disk when they are opened for the first time.'> like)." <category: 'accessing'> - ^self getDateAndTime: self stat stCtime value + ^self getDateAndTime: self stat stCtime ] lastModifyTime [ @@ -609,30 +609,17 @@ up being on disk when they are opened for the first time.'> (the `last modify time' has to do with the actual file contents)." <category: 'accessing'> - ^self getDateAndTime: self stat stMtime value + ^self getDateAndTime: self stat stMtime ] - finalize [ - "Free the statistics for the receiver" - - <category: 'accessing'> - | statVar | - statVar := stat. - stat := nil. - statVar free - ] - refresh [ "Refresh the statistics for the receiver" <category: 'accessing'> - stat isNil - ifTrue: - [stat := CStatStruct new. - self addToBeFinalized]. + stat isNil ifTrue: [stat := Kernel.Stat new]. self lstatOn: self realFileName into: stat. File checkError. - isSymbolicLink := (stat stMode value bitAnd: 61440) = 40960. "S_IFLNK" + isSymbolicLink := (stat stMode bitAnd: 61440) = 40960. "S_IFLNK" isSymbolicLink ifTrue: [self statOn: self realFileName into: stat. @@ -643,13 +630,10 @@ up being on disk when they are opened for the first time.'> "Answer whether a file with the name contained in the receiver does exist." <category: 'testing'> - stat isNil - ifTrue: - [stat := CStatStruct new. - self addToBeFinalized]. + stat isNil ifTrue: [stat := Kernel.Stat new]. self lstatOn: self realFileName into: stat. File errno == 0 ifFalse: [^false]. - isSymbolicLink := (stat stMode value bitAnd: 61440) = 40960. "S_IFLNK" + isSymbolicLink := (stat stMode bitAnd: 61440) = 40960. "S_IFLNK" isSymbolicLink ifTrue: [self statOn: self realFileName into: stat]. ^true ] @@ -1652,13 +1636,16 @@ ArchiveMemberHandler subclass: TmpFileArchiveMemberHandler [ -Namespace current: VFS [ +Namespace current: Kernel [ -CStruct subclass: CStatStruct [ +Object subclass: Stat [ - <category: 'Streams-Files'> - <comment: nil> - <declaration: #(#(#stMode #uShort ) #(#stSize #long ) #(#stAtime #long ) #(#stMtime #long ) #(#stCtime #long ) )> + | stMode stSize stAtime stMtime stCtime | + stMode [ ^stMode ] + stSize [ ^stSize ] + stAtime [ ^stAtime ] + stMtime [ ^stMtime ] + stCtime [ ^stCtime ] ] ] diff --git a/libgst/cint.c b/libgst/cint.c index 78e3715..1ad6e5a 100644 --- a/libgst/cint.c +++ b/libgst/cint.c @@ -105,15 +105,25 @@ typedef struct cfunc_info } cfunc_info; -typedef struct gst_stat +struct gst_stat_struct { unsigned short st_mode; /* protection */ long st_size; /* total size, in bytes */ long st_aTime; /* time of last access */ long st_mTime; /* time of last modification */ long st_cTime; /* time of last change */ +}; + +typedef struct gst_stat +{ + OBJ_HEADER; + OOP st_mode; /* protection */ + OOP st_size; /* total size, in bytes */ + OOP st_aTime; /* time of last access */ + OOP st_mTime; /* time of last modification */ + OOP st_cTime; /* time of last change */ } -gst_stat; +*gst_stat; @@ -168,10 +178,14 @@ static OOP classify_type_symbol (OOP symbolOOP, static int get_errno (void); /* Encapsulate binary incompatibilities between various C libraries. */ +static int my_stat_old (const char *name, + struct gst_stat_struct * out); +static int my_lstat_old (const char *name, + struct gst_stat_struct * out); static int my_stat (const char *name, - gst_stat * out); + OOP out); static int my_lstat (const char *name, - gst_stat * out); + OOP out); static int my_putenv (const char *str); static int my_chdir (const char *str); static int my_symlink (const char* oldpath, const char* newpath); @@ -284,48 +298,97 @@ get_errno (void) return (old); } +static inline int +adjust_time (time_t t) +{ + return _gst_adjust_time_zone (t) - 86400 * 10957; +} + +static inline int +my_stat_old (const char *name, + struct gst_stat_struct * out) +{ + int result; + struct stat statOut; + + result = stat (name, &statOut); + if (!result) + { + errno = 0; + out->st_mode = statOut.st_mode; + out->st_size = statOut.st_size; + out->st_aTime = adjust_time (statOut.st_atime); + out->st_mTime = adjust_time (statOut.st_mtime); + out->st_cTime = adjust_time (statOut.st_ctime); + } + return (result); +} + int my_stat (const char *name, - gst_stat * out) + OOP out) { int result; - static struct stat statOut; + struct stat statOut; result = stat (name, &statOut); if (!result) { + gst_stat obj = (gst_stat) OOP_TO_OBJ (out); + errno = 0; + obj->st_mode = FROM_INT (statOut.st_mode); + obj->st_aTime = FROM_INT (adjust_time (statOut.st_atime)); + obj->st_mTime = FROM_INT (adjust_time (statOut.st_mtime)); + obj->st_cTime = FROM_INT (adjust_time (statOut.st_ctime)); + obj->st_size = FROM_OFF_T (statOut.st_size); + } + return (result); +} + +#ifdef HAVE_LSTAT +static inline int +my_lstat_old (const char *name, + struct gst_stat_struct * out) +{ + int result; + struct stat statOut; + + result = lstat (name, &statOut); + if (!result) + { errno = 0; out->st_mode = statOut.st_mode; out->st_size = statOut.st_size; - out->st_aTime = _gst_adjust_time_zone (statOut.st_atime) - 86400 * 10957; - out->st_mTime = _gst_adjust_time_zone (statOut.st_mtime) - 86400 * 10957; - out->st_cTime = _gst_adjust_time_zone (statOut.st_ctime) - 86400 * 10957; + out->st_aTime = adjust_time (statOut.st_atime); + out->st_mTime = adjust_time (statOut.st_mtime); + out->st_cTime = adjust_time (statOut.st_ctime); } return (result); } -#ifdef HAVE_LSTAT int my_lstat (const char *name, - gst_stat * out) + OOP out) { int result; - static struct stat statOut; + struct stat statOut; result = lstat (name, &statOut); if (!result) { + gst_stat obj = (gst_stat) OOP_TO_OBJ (out); errno = 0; - out->st_mode = statOut.st_mode; - out->st_size = statOut.st_size; - out->st_aTime = _gst_adjust_time_zone (statOut.st_atime) - 86400 * 10957; - out->st_mTime = _gst_adjust_time_zone (statOut.st_mtime) - 86400 * 10957; - out->st_cTime = _gst_adjust_time_zone (statOut.st_ctime) - 86400 * 10957; + obj->st_mode = FROM_INT (statOut.st_mode); + obj->st_aTime = FROM_INT (adjust_time (statOut.st_atime)); + obj->st_mTime = FROM_INT (adjust_time (statOut.st_mtime)); + obj->st_cTime = FROM_INT (adjust_time (statOut.st_ctime)); + obj->st_size = FROM_OFF_T (statOut.st_size); } return (result); } #else #define my_lstat my_stat +#define my_lstat_old my_stat_old #endif int @@ -493,8 +556,10 @@ _gst_init_cfuncs (void) _gst_define_cfunc ("errno", get_errno); _gst_define_cfunc ("strerror", strerror); - _gst_define_cfunc ("stat", my_stat); - _gst_define_cfunc ("lstat", my_lstat); + _gst_define_cfunc ("stat", my_stat_old); + _gst_define_cfunc ("lstat", my_lstat_old); + _gst_define_cfunc ("stat_obj", my_stat); + _gst_define_cfunc ("lstat_obj", my_lstat); _gst_define_cfunc ("utime", _gst_set_file_access_times); _gst_define_cfunc ("chmod", chmod); diff --git a/libgst/dict.inl b/libgst/dict.inl index 4aaa204..b46d2bf 100644 --- a/libgst/dict.inl +++ b/libgst/dict.inl @@ -262,6 +262,16 @@ static inline int64_t to_c_int_64 (OOP oop); #define IS_C_ULONG(oop) is_c_uint_64(oop) #endif +#if SIZEOF_OFF_T == 4 +#define FROM_OFF_T(integer) from_c_int_32(integer) +#define TO_OFF_T(integer) to_c_int_32(integer) +#define IS_OFF_T(oop) is_c_int_32(oop) +#else +#define FROM_OFF_T(integer) from_c_int_64(integer) +#define TO_OFF_T(integer) to_c_int_64(integer) +#define IS_OFF_T(oop) is_c_int_64(oop) +#endif + /* Answer the INDEX'th instance variable of RECEIVER. */ #define INSTANCE_VARIABLE(receiver, index) \ (OOP_TO_OBJ (receiver)->data[index]) diff --git a/libgst/prims.def b/libgst/prims.def index 69ba211..714c028 100644 --- a/libgst/prims.def +++ b/libgst/prims.def @@ -71,16 +71,6 @@ #define PRIM_USES_GMP PRIM_FAIL #endif -#if SIZEOF_OFF_T == 4 -#define FROM_OFF_T(integer) from_c_int_32(integer) -#define TO_OFF_T(integer) to_c_int_32(integer) -#define IS_OFF_T(oop) is_c_int_32(oop) -#else -#define FROM_OFF_T(integer) from_c_int_64(integer) -#define TO_OFF_T(integer) to_c_int_64(integer) -#define IS_OFF_T(oop) is_c_int_64(oop) -#endif - #ifdef ENABLE_JIT_TRANSLATION #define PRIM_FAILED return ((intptr_t) -1) #define PRIM_SUCCEEDED return ((intptr_t) 0) _______________________________________________ help-smalltalk mailing list [hidden email] http://lists.gnu.org/mailman/listinfo/help-smalltalk |
Free forum by Nabble | Edit this page |