[79538] branches/gsoc11-rev-upgrade/base/src/pextlib1.0/Pextlib.c

cal at macports.org cal at macports.org
Thu Jun 16 16:41:49 PDT 2011


Revision: 79538
          http://trac.macports.org/changeset/79538
Author:   cal at macports.org
Date:     2011-06-16 16:41:48 -0700 (Thu, 16 Jun 2011)
Log Message:
-----------
rev-upgrade: new pextlib command to find out whether a file is binary

Modified Paths:
--------------
    branches/gsoc11-rev-upgrade/base/src/pextlib1.0/Pextlib.c

Modified: branches/gsoc11-rev-upgrade/base/src/pextlib1.0/Pextlib.c
===================================================================
--- branches/gsoc11-rev-upgrade/base/src/pextlib1.0/Pextlib.c	2011-06-16 21:24:50 UTC (rev 79537)
+++ branches/gsoc11-rev-upgrade/base/src/pextlib1.0/Pextlib.c	2011-06-16 23:41:48 UTC (rev 79538)
@@ -46,6 +46,7 @@
 #include <grp.h>
 #include <limits.h>
 #include <pwd.h>
+#include <stdbool.h>
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -53,6 +54,15 @@
 #include <strings.h>
 #include <unistd.h>
 
+/*
+  people use this on non-mac systems
+  #include <mach-o/loader.h>
+  #include <mach-o/fat.h>
+*/
+#define MH_MAGIC    (0xfeedface)
+#define MH_MAGIC_64 (0xfeedfacf)
+#define FAT_MAGIC   (0xcafebabe)
+
 #include <tcl.h>
 
 #include "Pextlib.h"
@@ -463,6 +473,96 @@
     return TCL_OK;
 }
 
+int fileIsBinaryCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) {
+    const char *path;
+    FILE *file;
+    uint32_t magic;
+    struct stat st;
+
+    if (objc != 2) {
+        Tcl_WrongNumArgs(interp, 1, objv, "filename");
+        return TCL_ERROR;
+    }
+
+    path = Tcl_GetString(objv[1]);
+    if (-1 == lstat(path, &st)) {
+        /* an error occured */
+        Tcl_SetErrno(errno);
+        Tcl_ResetResult(interp);
+        Tcl_AppendResult(interp, "lstat(", path, "):", (char *)Tcl_PosixError(interp), NULL);
+        return TCL_ERROR;
+    }
+    if (!S_ISREG(st.st_mode)) {
+        /* not a regular file, haven't seen directories which are binaries yet */
+        Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+        return TCL_OK;
+    }
+    if (NULL == (file = fopen(path, "r"))) {
+        Tcl_SetErrno(errno);
+        Tcl_ResetResult(interp);
+        Tcl_AppendResult(interp, "fopen(", path, "): ", (char *)Tcl_PosixError(interp), NULL);
+        return TCL_ERROR;
+    }
+    if (1 != fread(&magic, sizeof(uint32_t), 1, file)) {
+        if (feof(file)) {
+            fclose(file);
+            /* file is shorter than 4 byte, probably not a binary */
+            Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+            return TCL_OK;
+        }
+        /* error while reading */
+        Tcl_SetErrno(errno);
+        Tcl_ResetResult(interp);
+        Tcl_AppendResult(interp, "fread(&magic, 4, 1, ", path, "): ", (char *)Tcl_PosixError(interp), NULL);
+        fclose(file);
+        return TCL_ERROR;
+    }
+    if (magic == MH_MAGIC || magic == MH_MAGIC_64) {
+        fclose(file);
+        /* this is a mach-o file */
+        Tcl_SetObjResult(interp, Tcl_NewBooleanObj(true));
+        return TCL_OK;
+    }
+    if (magic == htonl(FAT_MAGIC)) {
+        uint32_t archcount;
+        /* either universal binary or java class (FAT_MAGIC == 0xcafebabe)
+           see /use/share/file/magic/cafebabe for an explanation of what I'm doing here */
+        if (1 != fread(&archcount, sizeof(uint32_t), 1, file)) {
+            if (feof(file)) {
+                fclose(file);
+                /* file shorter than 8 byte, probably not a binary either */
+                Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+                return TCL_OK;
+            }
+            /* error while reading */
+            Tcl_SetErrno(errno);
+            Tcl_ResetResult(interp);
+            Tcl_AppendResult(interp, "fread(&archcount, 4, 1, ", path, "): ", (char *)Tcl_PosixError(interp), NULL);
+            fclose(file);
+            return TCL_ERROR;
+        }
+
+        /* universal binary header is always big endian */
+        archcount = ntohl(archcount);
+        if (archcount > 0 && archcount < 20) {
+            fclose(file);
+            /* universal binary */
+            Tcl_SetObjResult(interp, Tcl_NewBooleanObj(true));
+            return TCL_OK;
+        }
+
+        fclose(file);
+        /* probably java class */
+        Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+        return TCL_OK;
+    }
+    fclose(file);
+
+    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false));
+    return TCL_OK;
+}
+
+
 int Pextlib_Init(Tcl_Interp *interp)
 {
 	if (Tcl_InitStubs(interp, "8.4", 0) == NULL)
@@ -495,6 +595,7 @@
 	Tcl_CreateObjCommand(interp, "symlink", CreateSymlinkCmd, NULL, NULL);
 	Tcl_CreateObjCommand(interp, "unsetenv", UnsetEnvCmd, NULL, NULL);
 	Tcl_CreateObjCommand(interp, "lchown", lchownCmd, NULL, NULL);
+	Tcl_CreateObjCommand(interp, "fileIsBinary", fileIsBinaryCmd, NULL, NULL);
 	Tcl_CreateObjCommand(interp, "realpath", RealpathCmd, NULL, NULL);
 
 	Tcl_CreateObjCommand(interp, "readline", ReadlineCmd, NULL, NULL);
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.macosforge.org/pipermail/macports-changes/attachments/20110616/96bc20d5/attachment.html>


More information about the macports-changes mailing list