help-smalltalk
[Top][All Lists]
Advanced

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

reply via email to

[Prev in Thread] Current Thread [Next in Thread]