Can I find a filename from a filehandle in Tcl?
Asked Answered
B

3

5

Similar to Can I find a filename from a filehandle in Perl? but in Tcl.

I plan to cache filename-filehandle associations anyway, so I'm asking purely out of curiosity--particularly of the "operating system wizardry" mentioned in the link. Is it possible in Tcl?

If it matters, I'm (forced into) using Tcl 8.0.5 on SunOS 5.10.

Berber answered 28/2, 2012 at 17:2 Comment(1)
8.0.5 is really seriously ancient. It's been out of support for over a decade.Safeconduct
S
6

With a version of Tcl that old, you really don't have all that many options. The simplest is to do a little bit of wrapping of open and close:

rename open _original_open
rename close _original_close

proc open {filename args} {
    global fileForChannel
    set channel [eval [list _original_open $filename] $args]
    set fileForChannel($channel) $filename
    return $channel
}
proc close {channel} {
    global fileForChannel
    catch {unset fileForChannel($channel)}
    _original_close $channel
}

Then, you can get the filename for an open channel $ch by just reading $fileForChannel($ch).

Safeconduct answered 28/2, 2012 at 19:48 Comment(2)
On Unix, you probably don't need to wrap close as channel names tend to be selected from a small set. Were you on Windows, it would be important to clean up as channel names there are more diverse. (This is due to the different nature of file descriptors on the two platforms.)Safeconduct
This is effectively what I have done--though I did not think of wrapping close. Thank you.Berber
B
1

I looked and did not find any way to get file name from handle, so I created my own solution. This solution uses the trace command to catch when the open command exits. At which time, both file names and handles are available, so I associate them to each other via the global fileNameFromHandle array.

# This script demonstrate the use of the trace command to keep track
# the relationship between file handles and file names

# ======================================================================
# Setup trace to track file handle vs. file name
array set fileNameFromHandle {}
proc trace_proc {command code result op} {
    if {$code != 0} return; # Ignore failed calls

    set filename [lindex $command 1]; # command = {open filename mode}
    set filehandle $result
    set ::fileNameFromHandle($filehandle) $filename
}
proc getFileName {handle} { return $::fileNameFromHandle($handle) }
trace add execution open leave trace_proc

# ======================================================================
# Main
set handle1 [open file1.txt r]

# Do something with the files

# Need filename from handle?
puts "Handle: $handle1, filename: [getFileName $handle1]"

close $handle1

Update

I don't have Tcl 8.0.5, to verify if this solution works. Please try it out and let me know. You can also trace the close command to remove the association.

Brandybrandyn answered 28/2, 2012 at 19:33 Comment(1)
Thanks for the suggestion Hai. Unfortunately, as @DonalFellows comments, command tracing is not available in Tcl 8.0.5. "This command causes Tcl commands to be executed whenever certain operations are invoked. At present, only variable tracing is implemented. [...]"Berber
A
0

You can run: exec lsof | grep -w [pid] | grep -w [fstat $file_handle ino]

Ainslie answered 23/6, 2015 at 8:19 Comment(1)
Could you please elaborate more your answer adding a little more description about the solution you provide?Irrefutable

© 2022 - 2024 — McMap. All rights reserved.