#!/bin/sh
: ; exec klone $0 "$@"
; The above line finds the klone executable in the $PATH
;;Skeleton of a typical klone script
;;(stack-dump-on-error t)
;;(kdb t)
(setq args (getopts "USAGE: vcat [file]
like cat, but outputs on stderr a dot per k read (or per chunk)
cats file or stdin if no file specified or file is -
"
("-m" () meg "output a dot per megabyte read (i.e: -c 1024)")
("-g" () bargraph "bargraph output. needs -b option")
("-b" bytes bytes "expected size in bytes for bargraph. will only copy
this number of bytes
defaults to the size of file if not stdin.")
("-o" file outfilename "output to file. default to stdout")
("-n" () null "output file to /dev/null")
("-q" () quiet "quiet, no output to stderr. maybe useful with -r")
("-skip" bytes skip "skip N first bytes")
("-c" bytes chunk-size "chunk (bytes per dot) size in K. default to 1")
("-r" N max-retries "in case of read errors, retry N times. default 0")
("-i" () ignore_errors "in case of read errors, ignore a sector")
("-ss" sector_size sector_size "sector size to ignore in bytes (def. 1)")
("-slow" N slow "sets chuncksize to 1K after N bytes")
("-s" () showspeed "display instant transfer speed under the bargraph")
))
(setq chuncksize (if meg (* 1024 1024) 1024))
(if (not sector_size) (setq sector_size 1))
(setq sector_size (Int sector_size))
(if chunk-size (setq chuncksize (* 1024 (Int chunk-size))))
(setq fdout (if outfilename
(open outfilename :direction :output :if-exists :supersede)
*standard-output*
))
(setq bytes (if bytes (Int bytes) 0))
(setq skip (if skip (Int skip) 0))
(setq slow (if slow (Int slow) *maxint*))
(if (and bargraph (<= bytes 0) (not (and args (/= "-" (0 args))))) (progn
(print-format *standard-error* "vcat error: -g requires -b\n")
(exit 1)
))
(setq max-retries (if max-retries (Int max-retries) 0))
(if quiet
(defmacro P (&rest args) ())
(defmacro P (&rest args) `(print-format *standard-error* ,@args))
)
(defun main (&aux
(size skip)
elapsed-time
(retries max-retries)
curtime
(start-time (mod (get-internal-run-time) *maxint*))
(toread chuncksize)
)
(if (and args (/= "-" (0 args)))
(progn
(setq fdin (open (0 args)))
(file-position fdin skip)
(if (<= bytes 0)
(setq bytes (get (file-stats (0 args)) 'size))
)
)
(progn
(setq fdin *standard-input*)
(if (/= 0 skip)
(dotimes (i (/ skip chuncksize)) (read-chars chuncksize fdin))
(read-chars (- skip (* chuncksize (/ skip chuncksize))) fdin)
)))
(init-display)
(catch 'EOF
(while t
(if (>= size slow)
(setq toread 1024) ;sets buffer to 1k before end
)
(setq buffer (read-chars toread fdin))
(if (> (length buffer) 0) (progn
(incf size (length buffer))
(show-progress size)
(if (/= retries max-retries) (progn ;there was an error
(P "Read error at byte %0, but OK after %1 retries!\n\e[A"
(- max-retries retries)
)
(setq retries max-retries)
))
)
(if (> retries 0) (progn
(P "Read error at byte %0, retrying %1 times... !\n\e[A"
size retries
)
(incf retries -1)
)
(if ignore_errors
(with (n (- sector_size (mod size sector_size)))
(P "vcat: read error at byte %0! chunk filled with %1 0s... \n"
size n)
(setq buffer (make-string n 0))
(incf size (length buffer))
(file-position fdin size)
)
(progn
(P "vcat: read error at byte %0! \n"
size)
(end start-time size 2)
))))
(if (not null)
(if (/= (length buffer)
(write-chars buffer () fdout)
)
(progn
(P "vcat: write error at byte %0! \n"
size)
(end start-time size 2)
)))
(if (and (> bytes 0) (>= size bytes))
(end start-time size 0)
)
))
(end start-time size 0)
)
(defun show-progress-dot (size)
(write-char #\. *standard-error*)
)
(defun init-display ()
(setq show-progress
(if
quiet ()
bargraph
(progn (ascii-progress-bar 0 bytes)
(if showspeed
ascii-progress-bar-with-speed
ascii-progress-bar
)
)
show-progress-dot))
)
(defun end (start-time size code &aux elapsed-time)
(if (not quiet) (progn
(setq elapsed-time
(+ 1 (- (mod (get-internal-run-time) *maxint*) start-time)))
(print-format *standard-error*
"%5%0 chars (%1k, %2M) read in %3ms (%4 bytes per second)\n"
size (/ size 1024) (/ size (* 1024 1024))
elapsed-time
(with (bps (Int (/ size (/ elapsed-time 1000.))))
(if (< bps 64000) bps (+ (String (/ bps 1024)) " kilo"))
)
(if bargraph "" "\n")
)))
(flush ())
(exit code)
)
(main)
;;; EMACS MODES
;;; Local Variables: ***
;;; mode:lisp ***
;;; End: ***
syntax highlighted by Code2HTML, v. 0.9.1