New Ticket     Tickets     Wiki     Browse Source     Timeline     Roadmap     Ticket Reports     Search

Changeset 79538


Ignore:
Timestamp:
06/16/11 16:41:48 (4 years ago)
Author:
cal@…
Message:

rev-upgrade: new pextlib command to find out whether a file is binary

File:
1 edited

Legend:

Unmodified
Added
Removed
  • branches/gsoc11-rev-upgrade/base/src/pextlib1.0/Pextlib.c

    r74010 r79538  
    4747#include <limits.h> 
    4848#include <pwd.h> 
     49#include <stdbool.h> 
    4950#include <stdint.h> 
    5051#include <stdio.h> 
     
    5354#include <strings.h> 
    5455#include <unistd.h> 
     56 
     57/* 
     58  people use this on non-mac systems 
     59  #include <mach-o/loader.h> 
     60  #include <mach-o/fat.h> 
     61*/ 
     62#define MH_MAGIC    (0xfeedface) 
     63#define MH_MAGIC_64 (0xfeedfacf) 
     64#define FAT_MAGIC   (0xcafebabe) 
    5565 
    5666#include <tcl.h> 
     
    464474} 
    465475 
     476int fileIsBinaryCmd(ClientData clientData UNUSED, Tcl_Interp *interp, int objc, Tcl_Obj *CONST objv[]) { 
     477    const char *path; 
     478    FILE *file; 
     479    uint32_t magic; 
     480    struct stat st; 
     481 
     482    if (objc != 2) { 
     483        Tcl_WrongNumArgs(interp, 1, objv, "filename"); 
     484        return TCL_ERROR; 
     485    } 
     486 
     487    path = Tcl_GetString(objv[1]); 
     488    if (-1 == lstat(path, &st)) { 
     489        /* an error occured */ 
     490        Tcl_SetErrno(errno); 
     491        Tcl_ResetResult(interp); 
     492        Tcl_AppendResult(interp, "lstat(", path, "):", (char *)Tcl_PosixError(interp), NULL); 
     493        return TCL_ERROR; 
     494    } 
     495    if (!S_ISREG(st.st_mode)) { 
     496        /* not a regular file, haven't seen directories which are binaries yet */ 
     497        Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false)); 
     498        return TCL_OK; 
     499    } 
     500    if (NULL == (file = fopen(path, "r"))) { 
     501        Tcl_SetErrno(errno); 
     502        Tcl_ResetResult(interp); 
     503        Tcl_AppendResult(interp, "fopen(", path, "): ", (char *)Tcl_PosixError(interp), NULL); 
     504        return TCL_ERROR; 
     505    } 
     506    if (1 != fread(&magic, sizeof(uint32_t), 1, file)) { 
     507        if (feof(file)) { 
     508            fclose(file); 
     509            /* file is shorter than 4 byte, probably not a binary */ 
     510            Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false)); 
     511            return TCL_OK; 
     512        } 
     513        /* error while reading */ 
     514        Tcl_SetErrno(errno); 
     515        Tcl_ResetResult(interp); 
     516        Tcl_AppendResult(interp, "fread(&magic, 4, 1, ", path, "): ", (char *)Tcl_PosixError(interp), NULL); 
     517        fclose(file); 
     518        return TCL_ERROR; 
     519    } 
     520    if (magic == MH_MAGIC || magic == MH_MAGIC_64) { 
     521        fclose(file); 
     522        /* this is a mach-o file */ 
     523        Tcl_SetObjResult(interp, Tcl_NewBooleanObj(true)); 
     524        return TCL_OK; 
     525    } 
     526    if (magic == htonl(FAT_MAGIC)) { 
     527        uint32_t archcount; 
     528        /* either universal binary or java class (FAT_MAGIC == 0xcafebabe) 
     529           see /use/share/file/magic/cafebabe for an explanation of what I'm doing here */ 
     530        if (1 != fread(&archcount, sizeof(uint32_t), 1, file)) { 
     531            if (feof(file)) { 
     532                fclose(file); 
     533                /* file shorter than 8 byte, probably not a binary either */ 
     534                Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false)); 
     535                return TCL_OK; 
     536            } 
     537            /* error while reading */ 
     538            Tcl_SetErrno(errno); 
     539            Tcl_ResetResult(interp); 
     540            Tcl_AppendResult(interp, "fread(&archcount, 4, 1, ", path, "): ", (char *)Tcl_PosixError(interp), NULL); 
     541            fclose(file); 
     542            return TCL_ERROR; 
     543        } 
     544 
     545        /* universal binary header is always big endian */ 
     546        archcount = ntohl(archcount); 
     547        if (archcount > 0 && archcount < 20) { 
     548            fclose(file); 
     549            /* universal binary */ 
     550            Tcl_SetObjResult(interp, Tcl_NewBooleanObj(true)); 
     551            return TCL_OK; 
     552        } 
     553 
     554        fclose(file); 
     555        /* probably java class */ 
     556        Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false)); 
     557        return TCL_OK; 
     558    } 
     559    fclose(file); 
     560 
     561    Tcl_SetObjResult(interp, Tcl_NewBooleanObj(false)); 
     562    return TCL_OK; 
     563} 
     564 
     565 
    466566int Pextlib_Init(Tcl_Interp *interp) 
    467567{ 
     
    496596        Tcl_CreateObjCommand(interp, "unsetenv", UnsetEnvCmd, NULL, NULL); 
    497597        Tcl_CreateObjCommand(interp, "lchown", lchownCmd, NULL, NULL); 
     598        Tcl_CreateObjCommand(interp, "fileIsBinary", fileIsBinaryCmd, NULL, NULL); 
    498599        Tcl_CreateObjCommand(interp, "realpath", RealpathCmd, NULL, NULL); 
    499600 
Note: See TracChangeset for help on using the changeset viewer.