Changeset 13378


Ignore:
Timestamp:
Aug 6, 2005, 10:33:35 AM (15 years ago)
Author:
pguyot (Paul Guyot)
Message:

Fixed a problem introduced with latest commit (-t would no longer work).
darwintrace now reports full paths (but not normalized) using getcwd (which
calls open, btw) and no longer reports directories (thus we don't have the
additional entries created by calls to getcwd).
Added a new feature of -t: tracking created files outside work (except during
install and activate targets). This is not complete (only open is patched) and
still experimental.
Experimental work on getting all the output of darwintrace. The last lines are
sometimes lost.

Location:
trunk/base/src
Files:
4 edited

Legend:

Unmodified
Added
Removed
  • trunk/base/src/darwintracelib1.0/Makefile

    r13169 r13378  
    77include ../../Mk/dports.autoconf.mk
    88include ../../Mk/dports.tea.mk
     9
     10CFLAGS+=        -DDARWINTRACE_LOG_CREATE
  • trunk/base/src/darwintracelib1.0/darwintrace.c

    r13220 r13378  
    4242#include <sys/syscall.h>
    4343
     44/*
     45 * Compile time options:
     46 * DARWINTRACE_SHOW_PROCESS: show the process id of every access
     47 * DARWINTRACE_LOG_CREATE: log creation of files as well.
     48 */
     49
     50/*
     51 * Prototypes.
     52 */
     53void log_op(const char* op, const char* path, int fd);
     54void __darwintrace_setup();
     55
    4456int __darwintrace_fd = -2;
    4557#define BUFFER_SIZE     1024
     
    5163
    5264inline void __darwintrace_setup() {
     65#define open(x,y,z) syscall(SYS_open, (x), (y), (z))
    5366        if (__darwintrace_fd == -2) {
    5467          char* path = getenv("DARWINTRACE_LOG");
     
    6982        }
    7083#endif
     84#undef open
     85}
     86
     87/* log a call and optionally get the real path from the fd if it's not 0.
     88 */
     89void log_op(const char* op, const char* path, int fd) {
     90        int size;
     91        char somepath[MAXPATHLEN];
     92        if((fd > 0) && (strncmp(path, "/.vol/", 6) == 0)) {
     93                if(0 == fcntl(fd, F_GETPATH, somepath)) {
     94#if DARWINTRACE_SHOW_PROCESS
     95                        size = snprintf(__darwintrace_buf, BUFFER_SIZE, "%s[%d]\t%s\t%s\n", __darwintrace_progname, __darwintrace_pid, op, somepath );
     96                        /* printf("resolved %s to %s\n", path, realpath); */
     97#else
     98                        size = snprintf(__darwintrace_buf, BUFFER_SIZE, "%s\t%s\n", op, somepath );
     99#endif
     100                } else {
     101                        /* if we can't resolve it, ignore the volfs path */
     102                        size = 0;
     103                }
     104        } else {
     105                /* append cwd to the path if required */
     106                if (path[0] != '/') {
     107                        (void) getcwd(somepath, sizeof(somepath));
     108#if DARWINTRACE_SHOW_PROCESS
     109                        size = snprintf(__darwintrace_buf,
     110                                                BUFFER_SIZE, "%s[%d]\t%s\t%s/%s\n",
     111                                                __darwintrace_progname, __darwintrace_pid,
     112                                                op, somepath, path );
     113#else
     114                        size = snprintf(__darwintrace_buf,
     115                                                BUFFER_SIZE, "%s\t%s/%s\n", op, somepath, path );
     116#endif
     117                } else {
     118#if DARWINTRACE_SHOW_PROCESS
     119                        size = snprintf(__darwintrace_buf,
     120                                                BUFFER_SIZE, "%s[%d]\t%s\t%s\n",
     121                                                __darwintrace_progname, __darwintrace_pid,
     122                                                op, path );
     123#else
     124                        size = snprintf(__darwintrace_buf,
     125                                                BUFFER_SIZE, "%s\t%s\n", op, path );
     126#endif
     127                }
     128        }
     129        write(__darwintrace_fd, __darwintrace_buf, size);
     130        fsync(__darwintrace_fd);
    71131}
    72132
    73133/* Log calls to open(2) into the file specified by DARWINTRACE_LOG.
    74134   Only logs if the DARWINTRACE_LOG environment variable is set.
     135   Only logs files (or rather, do not logs directories)
    75136   Only logs files where the open succeeds.
    76    Only logs files opened for read access, without the O_CREAT flag set.
     137   Only logs files opened for read access, without the O_CREAT flag set
     138        (except if DARWINTRACE_LOG_CREATE is set).
    77139   The assumption is that any file that can be created isn't necessary
    78140   to build the project.
     
    89151        va_end(args);
    90152        result = open(path, flags, mode);
    91         if (result >= 0 && (flags & (O_CREAT | O_WRONLY /*O_RDWR*/)) == 0 ) {
    92                 __darwintrace_setup();
    93                 if (__darwintrace_fd >= 0) {
    94                   int size;
    95                   if(strncmp(path, "/.vol/", 6) == 0) {
    96                     char realpath[MAXPATHLEN];
    97                     if(0 == fcntl(result, F_GETPATH, realpath)) {
    98 #if DARWINTRACE_SHOW_PROCESS
    99                       size = snprintf(__darwintrace_buf, BUFFER_SIZE, "%s[%d]\topen\t%s\n", __darwintrace_progname, __darwintrace_pid, realpath );
    100                       /* printf("resolved %s to %s\n", path, realpath); */
    101 #else
    102                       size = snprintf(__darwintrace_buf, BUFFER_SIZE, "open\t%s\n", realpath );
    103 #endif
    104                     } else {
    105                     /* if we can't resolve it, ignore the volfs path */
    106                       size = 0;
    107                     }
    108                   } else {
    109 #if DARWINTRACE_SHOW_PROCESS
    110                     size = snprintf(__darwintrace_buf, BUFFER_SIZE, "%s[%d]\topen\t%s\n", __darwintrace_progname, __darwintrace_pid, path );
    111 #else
    112                         size = snprintf(__darwintrace_buf, BUFFER_SIZE, "open\t%s\n", path );
    113 #endif
    114                   }
    115                   write(__darwintrace_fd, __darwintrace_buf, size);
    116                   fsync(__darwintrace_fd);
     153        if (result >= 0) {
     154                /* check that it's a file */
     155                struct stat sb;
     156                fstat(result, &sb);
     157                if ((sb.st_mode & S_IFDIR) == 0) {
     158                        if ((flags & (O_CREAT | O_WRONLY /*O_RDWR*/)) == 0 ) {
     159                                __darwintrace_setup();
     160                                if (__darwintrace_fd >= 0) {
     161                                        log_op("open", path, result);
     162                                }
     163#if DARWINTRACE_LOG_CREATE
     164                        } else if (flags & O_CREAT) {
     165                                __darwintrace_setup();
     166                                if (__darwintrace_fd >= 0) {
     167                                        log_op("create", path, result);
     168                                }
     169#endif
     170                        }
    117171                }
    118172        }
    119173        return result;
     174#undef open
    120175}
    121176
     
    128183          struct stat sb;
    129184          if (stat(path, &sb) == 0) {
    130 #if DARWINTRACE_SHOW_PROCESS
    131                 int size = snprintf(__darwintrace_buf, BUFFER_SIZE, "%s[%d]\texecve\t%s\n", __darwintrace_progname, __darwintrace_pid, path );
    132 #else
    133                 int size = snprintf(__darwintrace_buf, BUFFER_SIZE, "execve\t%s\n", path );
    134 #endif
    135                 int fd;
    136                
    137                 write(__darwintrace_fd, __darwintrace_buf, size);
    138                 fsync(__darwintrace_fd);
     185                int fd;
     186               
     187                log_op("execve", path, 0);
    139188               
    140189                fd = open(path, O_RDONLY, 0);
     
    161210                                /* we have liftoff */
    162211                                if (interp) {
    163 #if DARWINTRACE_SHOW_PROCESS
    164                                         const char* procname = strrchr(argv[0], '/') + 1;
    165                                         if (procname == NULL) procname = argv[0];
    166                                         int size = snprintf(__darwintrace_buf, BUFFER_SIZE, "%s[%d]\texecve\t%s\n", procname, 0, interp );
    167 #else
    168                                         int size = snprintf(__darwintrace_buf, BUFFER_SIZE, "execve\t%s\n", interp );
    169 #endif
    170                                         write(__darwintrace_fd, __darwintrace_buf, size);
    171                                         fsync(__darwintrace_fd);
     212                                        log_op("execve", interp, 0);
    172213                                }
    173214                        }
  • trunk/base/src/port1.0/porttrace.tcl

    r13350 r13378  
    22# porttrace.tcl
    33#
    4 # $Id: porttrace.tcl,v 1.6 2005/08/04 12:55:39 pguyot Exp $
     4# $Id: porttrace.tcl,v 1.7 2005/08/06 10:33:35 pguyot Exp $
    55#
    66# Copyright (c) 2005 Paul Guyot <pguyot@kallisys.net>,
     
    5050                       
    5151                        # Create the thread/process.
    52                         create_slave $trace_fifo
     52                        create_slave $workpath $trace_fifo
    5353                                       
    5454                        # Launch darwintrace.dylib.
     
    7979}
    8080
     81# Check that no file were created outside workpath.
     82# Output a warning for every created file the trace revealed.
     83# This method must be called after trace_start
     84proc trace_check_create {} {
     85        global trace_mutex
     86        # Acquire the mutex.
     87        thread::mutex lock $trace_mutex
     88        # Get the list of created files.
     89        set created [slave_send slave_get_created]
     90        # Release the mutex.
     91        thread::mutex unlock $trace_mutex
     92       
     93        # Compare with portslist
     94        set created [lsort $created]
     95        foreach created_file $created {
     96                ui_warn "trace revealed an illegal file creation: $created_file"
     97        }
     98}
     99
    81100# Stop the trace and return the list of ports the port depends on.
    82101# This method must be called after trace_start
     
    101120# Private
    102121# Create the slave thread.
    103 proc create_slave {trace_fifo} {
    104         global trace_thread
     122proc create_slave {workpath trace_fifo} {
     123        global trace_thread trace_mutex
    105124        # Create the thread.
    106125        set trace_thread [thread::create -preserved {thread::wait}]
     126       
     127        # Create the mutex
     128        set trace_mutex [thread::mutex create]
    107129
    108130        # Tell the thread about all the Tcl packages we already
     
    132154
    133155        # Start the slave work.
    134         thread::send -async $trace_thread "slave_start $trace_fifo"
     156        thread::send -async $trace_thread "slave_start $trace_fifo $workpath $trace_mutex"
    135157}
    136158
     
    164186# Slave method to read a line from the trace.
    165187proc slave_read_line {chan} {
    166         global ports_list trace_filemap
    167 
    168         # We should never get EOF, actually.
    169         if {![eof $chan]} {
     188        global ports_list trace_filemap created_list workpath trace_mutex own_mutex
     189
     190        # Acquire the mutex.
     191        thread::mutex lock $trace_mutex
     192
     193        while 1 {
     194                # We should never get EOF, actually.
     195                if {[eof $chan]} {
     196                        break
     197                }
     198               
    170199                # The line is of the form: verb\tpath
    171200                # Get the path by chopping it.
    172201                set theline [gets $chan]
    173202               
     203                if {[fblocked $chan]} {
     204                        # Exit the loop.
     205                        break
     206                }
     207
    174208                set line_length [string length $theline]
    175209               
     
    177211                if {$line_length > 0} {
    178212                        set path_start [expr [string first "\t" $theline] + 1]
     213                        set op [string range $theline 0 [expr $path_start - 2]]
    179214                        set path [string range $theline $path_start [expr $line_length - 1]]
    180215                        set path [file normalize $path]
    181216                       
    182                         # Only work on files.
    183                         if {[file isfile $path]} {
    184                                 # Did we process the file yet?
    185                                 if {![filemap exists trace_filemap $path]} {
    186                                         # Obtain information about this file.
    187                                         set port [registry::file_registered $path]
    188                                         if { $port != 0 } {
    189                                                 # Add the port to the list.
    190                                                 if {[lsearch -sorted -exact $ports_list $port] == -1} {
    191                                                         lappend ports_list $port
    192                                                         set ports_list [lsort $ports_list]
    193                                                         # Maybe fill trace_filemap for efficiency?
     217                        # open/execve
     218                        if {$op == "open" || $op == "execve"} {
     219                                # Only work on files.
     220                                if {[file isfile $path]} {
     221                                        # Did we process the file yet?
     222                                        if {![filemap exists trace_filemap $path]} {
     223                                                # Obtain information about this file.
     224                                                set port [registry::file_registered $path]
     225                                                if { $port != 0 } {
     226                                                        # Add the port to the list.
     227                                                        if {[lsearch -sorted -exact $ports_list $port] == -1} {
     228                                                                lappend ports_list $port
     229                                                                set ports_list [lsort $ports_list]
     230                                                                # Maybe fill trace_filemap for efficiency?
     231                                                        }
    194232                                                }
     233                       
     234                                                # Add the file to the tree with port information.
     235                                                filemap set trace_filemap $path $port
    195236                                        }
    196                
    197                                         # Add the file to the tree with port information.
    198                                         filemap set trace_filemap $path $port
     237                                }
     238                        } elseif {$op == "create"} {
     239                                # Only keep entries not under workpath
     240                                if {![string equal -length [string length $workpath] $workpath $path]} {
     241                                        lappend created_list $path
    199242                                }
    200243                        }
    201244                }
    202245        }
     246
     247        thread::mutex unlock $trace_mutex
    203248}
    204249
    205250# Private.
    206251# Slave init method.
    207 proc slave_start {fifo} {
    208         global ports_list trace_filemap trace_fifo_r_chan trace_fifo_w_chan
     252proc slave_start {fifo p_workpath mutex} {
     253        global ports_list trace_filemap created_list trace_fifo_r_chan \
     254                trace_fifo_w_chan workpath trace_mutex own_mutex
     255        # Save the workpath and the mutex.
     256        set workpath $p_workpath
     257        set trace_mutex $mutex
     258        set own_mutex 0
    209259        # Create a virtual filemap.
    210260        filemap create trace_filemap
    211261        set ports_list {}
     262        set created_list {}
    212263        set trace_fifo_r_chan [open $fifo {RDONLY NONBLOCK}]
    213264        # To prevent EOF when darwintrace closes the file, I also open the pipe
     
    218269        # still being able to get commands thru thread::send). Thoughts, anyone?
    219270        set trace_fifo_w_chan [open $fifo w]
     271        fconfigure $trace_fifo_r_chan -blocking 0 -buffering line
    220272        fileevent $trace_fifo_r_chan readable [list slave_read_line $trace_fifo_r_chan]
    221273}
     
    238290        return $ports_list
    239291}
     292
     293# Private.
     294# Slave created export method.
     295proc slave_get_created {} {
     296        global created_list
     297        return $created_list
     298}
  • trunk/base/src/port1.0/portutil.tcl

    r13377 r13378  
    646646                        }
    647647
    648                         # Check dependencies.
     648                        # Check dependencies & files creates outside work.
    649649                        if {([info exists ports_trace] && $ports_trace == "yes")} {
    650650                                set depends {}
     
    652652                               
    653653                                # Determine deptypes to look for based on target
     654                                set target [ditem_key $ditem provides]
    654655                                switch $target {
    655656                                        configure       { set deptypes "depends_lib" }
     
    677678                                # Dependencies are in the form verb:[param:]port
    678679                                set depsPorts {}
    679                                 foreach dep $deps {
     680                                foreach dep $depends {
    680681                                        # grab the portname portion of the depspec
    681682                                        set portname [lindex [split $depspec :] end]
     
    683684                                }
    684685                                trace_check_deps $depsPorts
     686                               
     687                                # Check files that were created.
     688                                if {$target != "activate"
     689                                        || $target != "fetch"
     690                                        || $target != "install"} {
     691                                        trace_check_create
     692                                }
    685693                        }
    686694
Note: See TracChangeset for help on using the changeset viewer.