[PATCH] stat/lstat into a Smalltalk object

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|

[PATCH] stat/lstat into a Smalltalk object

Paolo Bonzini-2
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