🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: comp.unix.bsd
Article #6087

cmpmanifest - extended tcl program to compare a MANIFEST to what's really there

#6087
From: Karl Lehenbauer
Date: Thu, 23 Apr 1992 14:33
170 lines
5071 bytes
Here's an Extended Tcl program that reads a MANIFEST file and compares
a directory hierarchy to it, reporting the names of files that have been 
added, files that have changed, and files that are missing.  

#!/bin/tcl
#
# cmpmanifest.tcl - compare a MANIFEST against what's actually out there
#
# Version 1.1
#
# Copyright 1992 NeoSoft
#
# Permission to use, copy, modify, and distribute this software and its
# documentation for any purpose and without fee is hereby granted, provided
# that the above copyright notice appear in all copies.  NeoSoft makes
# no representations about the suitability of this  software for any 
# purpose.  It is provided "as is" without express or implied warranty.
#
# This program reads files containing entries of the form:
#
#104748588 1474560 srcfloppy.1
#
# and compares a directory tree to it, reporting files that are
# new since the MANIFEST was created, files that have
# changed, and files that are missing.
#
# To use, cd to the top-level directory of a distribution and do a
# cmpmanifest
#   or
# tcl cmpmanifest
#
# If the "-b" option is specified, the names of all files that are new or
# changed are output to standard output, without any other text, to generate
# lists of filenames for backups of changes and the like.

proc report_status {status fileName} {
    global changeReport

    if {$changeReport} {
        echo "$status: $fileName"
    }
}

proc report_backup {fileName} {
    global backupReport

    if {$backupReport} {
        echo "$fileName"
    }
}

proc load_manifest {manifestFileName} {
    global manifestData

    set fp [open $manifestFileName]

    while {[gets $fp cksumLine] >= 0} {

        set checkString [string trim $cksumLine]
        if {([cindex $checkString 0] == "#") || ($checkString == "")} {
            continue
        }

        set cksumData [lrange $cksumLine 0 1]
        set cksumFileName [lindex $cksumLine 2]

        keylset manifestData($cksumFileName) cksumData $cksumData
    }
}

proc compare_manifest {dir} {
    foreach dirEntry [lsort [glob -nocomplain $dir/* $dir/.*]] {
        if [string match "*/." $dirEntry] continue
        if [string match "*/.." $dirEntry] continue

        file lstat $dirEntry statBuf
        if {$statBuf(type) == "directory"} {
            compare_manifest $dirEntry
        }

	if {$statBuf(type) == "file"} {
            process_file $dirEntry
        }
    }
}

#
# process_file - this actually compares a file to what the manifest
# knew about it.
#
# If the lengths aren't the same, we don't bother to find the checkums,
# to improve performance.
#
proc process_file {fileName} {
    global manifestData

    if ![info exists manifestData($fileName)] {
        report_status new $fileName
        report_backup $fileName
        return
    }

    keylset manifestData($fileName) saw 1

    if {[catch {set testfp [open $fileName]} errorMessage] == 1} {
        report_status bad_file "$fileName $errorMessage"
        return
    }
    fstat $testfp actualStat
    close $testfp
    set cksumData [keylget manifestData($fileName) cksumData]
    if {$actualStat(size) == [lindex $cksumData 1]} {
        set actualCksumLine [exec cksum $fileName]
        set actualCksumData [lrange $actualCksumLine 0 1]

        if {$cksumData == $actualCksumData} {
            return
        }
    }
    report_status changed $fileName
    report_backup $fileName
}

proc whats_missing {} {
    global manifestData

    for_array_keys keyName manifestData {
        if ![keylget manifestData($keyName) saw dummy] {
            report_status missing $keyName
        }
    }
}

proc doit {} {
    puts stderr "loading MANIFEST file..."
    load_manifest MANIFEST
    puts stderr "comparing MANIFEST to disk..."
    compare_manifest .
    whats_missing
}

proc usage {} {
    puts stderr "usage: cd to top directory containing MANIFEST file"
    puts stderr "       and do a 'cmpmanifest' to get a change report"
    puts stderr "       or a 'cmpmanifest -b' to get a backup list"
    exit 1
}

global changeReport backupReport
set changeReport 1
set backupReport 0

if !$interactiveSession {
    if {![file readable MANIFEST]} {
        usage
    }
    if {$argv != ""} {
        if {$argv != "-b"} {
            usage
        } else {
            set backupReport 1
            set changeReport 0
        }
    }
    doit
    exit 0
}
-- 
-- Email info@NeoSoft.com for info on getting Internet access.
"Silent gratitude isn't very much use to anyone." -- G. B. Stearn
Technical Details
Message-ID: <1992Apr23.143346.7796@NeoSoft.com>
Path: arc1-ca.pugleaf.net!wupost!zaphod.mps.ohio-state.edu!menudo.uh.edu!sugar!karl

Show Full Headers
Complete Article Headers
Newsgroups: comp.unix.bsd,alt.sources,comp.lang.tcl
Path: arc1-ca.pugleaf.net!wupost!zaphod.mps.ohio-state.edu!menudo.uh.edu!sugar!karl
From: karl@NeoSoft.com (Karl Lehenbauer)
Subject: cmpmanifest - extended tcl program to compare a MANIFEST to what's really there
Organization: NeoSoft Communications Services -- (713) 684-5900
Date: Thu, 23 Apr 1992 14:33:46 GMT
Message-ID: <1992Apr23.143346.7796@NeoSoft.com>