Skip to content

zfs_versions.tcl


#!/usr/bin/tclsh
#
# CDDL HEADER START
#
# The contents of this file are subject to the terms of the
# Common Development and Distribution License (the "License").
# You may not use this file except in compliance with the License.
#
# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
# or http://www.opensolaris.org/os/licensing.
# See the License for the specific language governing permissions
# and limitations under the License.
#
# When distributing Covered Code, include this CDDL HEADER in each
# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
# If applicable, add the following below this CDDL HEADER, with the
# fields enclosed by brackets "[]" replaced with your own identifying
# information: Portions Copyright [yyyy] [name of copyright owner]
#
# CDDL HEADER END
#
# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
# Use is subject to license terms.
#
# needs tclsh8.4 to be large file aware so if you are looking for
# versions of large files don’t use this.
#

proc vputs {str verb} {
        global options
        if {[info exists options(verbose)] && $options(verbose) == 1 } {
                puts "$str $verb"
        } else {
                puts $str
        }
}
proc output { buf1 file } {
        upvar buf $buf1
        global options

        if [ info exists options(forX) ] {
        vputs "\"[clock format $buf(mtime)]\"\t$file" "[array get buf]"
        } else {
        vputs "[clock format $buf(mtime)]\t$file" "[array get buf]"
        }
}

proc do_file { fs file } {
        
        foreach snap [glob -nocomplain [file join $fs .zfs snapshot * $file] ] {
                if {[ catch {file stat $snap buf} err ] } {
                        puts stderr "$snap $err"
                        puts stdout "$snap"
                        continue
                }
                lappend x [ list $buf(mtime)$buf(ctime) $buf(ino) $snap [array get buf]]
        }
        if { ! [info exists x]} {
                if [ file exists [file join $fs $file]] {
                        puts [file join $fs $file]
                }
                return
        }
        set x [lsort $x]
        set lctime 0
        set lmtime 0
        set lino 0
        unset buf
        foreach snapl $x {
                set snap [lindex $snapl 2]
                array set buf [lindex $snapl 3]
                if { $lctime == $buf(ctime) && $lmtime == $buf(mtime) && $lino == $buf(ino) } {
                        unset buf
                        continue
                }
                set lctime $buf(ctime)
                set lmtime $buf(mtime)
                set lino $buf(ino)
                output buf $snap
                unset buf
        }
        if {[ catch {file stat [file join $fs $file] buf} x ] } {
                return
        }
        if { $lctime == $buf(ctime) && $lmtime == $buf(mtime) && $lino == $buf(ino) } {
                return
        }

        output buf [file join $fs $file]
}

proc absolute {path} {
        set x [split $path]
        if { [lindex $x 0] == "/" } {
                return $path
        } else {
                return [file join [pwd] $path]
        }
}

proc find_do_zfs {path} {
        set path [absolute $path]
        while { $path != "/" && ! [file exists $path/.zfs ] } {
                set x [file split $path]
                set path [file dirname $path]
                if [info exists p] {
                        set p [file join [lindex $x end] $p]
                } else {
                        set p [lindex $x end]
                }
        }
        return [list $path $p]
}

proc doit {file} {
        set f [find_do_zfs $file]
        do_file [lindex $f 0] [lindex $f 1]
}

set options(verbose) 0
if {[lindex $argv 0] == "-X" } {
        set options(forX) 1
        set argv [lrange $argv 1 end]
}
foreach arg $argv {
        doit $arg
}

Advertisements
%d bloggers like this: