[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Help-smalltalk] [PATCH] stat/lstat into a Smalltalk object
From: |
Paolo Bonzini |
Subject: |
[Help-smalltalk] [PATCH] stat/lstat into a Smalltalk object |
Date: |
Wed, 26 Mar 2008 09:42:57 +0100 |
User-agent: |
Thunderbird 2.0.0.12 (Macintosh/20080213) |
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 <address@hidden>
* 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)
[Prev in Thread] |
Current Thread |
[Next in Thread] |
- [Help-smalltalk] [PATCH] stat/lstat into a Smalltalk object,
Paolo Bonzini <=