This file is indexed.

/usr/lib/ruby/vendor_ruby/archive/tar/minitar/command.rb is in ruby-archive-tar-minitar 0.5.2-2.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
#!/usr/bin/env ruby
#--
# Archive::Tar::Baby 0.5.2
#   Copyright 2004 Mauricio Julio Ferna'ndez Pradier and Austin Ziegler
#   This is free software with ABSOLUTELY NO WARRANTY.
#
# This program is based on and incorporates parts of RPA::Package from
# rpa-base (lib/rpa/package.rb and lib/rpa/util.rb) by Mauricio and has been
# adapted to be more generic by Austin.
#
# This file contains an adaptation of Ruby/ProgressBar by Satoru
# Takabayashi <satoru@namazu.org>, copyright 2001 - 2004.
#
# It is licensed under the GNU General Public Licence or Ruby's licence.
#
# $Id: command.rb 213 2008-02-26 22:32:11Z austin $
#++

require 'zlib'

# TODO: add
# TODO: delete ???

require 'optparse'
require 'ostruct'
require 'fileutils'

module Archive::Tar::Minitar::Command
  class ProgressBar
    VERSION = "0.8"

    attr_accessor :total
    attr_accessor :title

    def initialize (title, total, out = STDERR)
      @title = title
      @total = total
      @out = out
      @bar_width = 80
      @bar_mark = "o"
      @current = 0
      @previous = 0
      @is_finished = false
      @start_time = Time.now
      @previous_time = @start_time
      @title_width = 14
      @format = "%-#{@title_width}s %3d%% %s %s"
      @format_arguments = [:title, :percentage, :bar, :stat]
      show
    end

  private
    def convert_bytes (bytes)
      if bytes < 1024
        sprintf("%6dB", bytes)
      elsif bytes < 1024 * 1000 # 1000kb
        sprintf("%5.1fKB", bytes.to_f / 1024)
      elsif bytes < 1024 * 1024 * 1000  # 1000mb
        sprintf("%5.1fMB", bytes.to_f / 1024 / 1024)
      else
        sprintf("%5.1fGB", bytes.to_f / 1024 / 1024 / 1024)
      end
    end

    def transfer_rate
      bytes_per_second = @current.to_f / (Time.now - @start_time)
      sprintf("%s/s", convert_bytes(bytes_per_second))
    end

    def bytes
      convert_bytes(@current)
    end

    def format_time (t)
      t = t.to_i
      sec = t % 60
      min  = (t / 60) % 60
      hour = t / 3600
      sprintf("%02d:%02d:%02d", hour, min, sec);
    end

    # ETA stands for Estimated Time of Arrival.
    def eta
      if @current == 0
        "ETA:  --:--:--"
      else
      elapsed = Time.now - @start_time
      eta = elapsed * @total / @current - elapsed;
      sprintf("ETA:  %s", format_time(eta))
      end
    end

    def elapsed
      elapsed = Time.now - @start_time
      sprintf("Time: %s", format_time(elapsed))
    end

    def stat
      if @is_finished then elapsed else eta end
    end

    def stat_for_file_transfer
      if @is_finished then 
        sprintf("%s %s %s", bytes, transfer_rate, elapsed)
      else 
        sprintf("%s %s %s", bytes, transfer_rate, eta)
      end
    end

    def eol
      if @is_finished then "\n" else "\r" end
    end

    def bar
      len = percentage * @bar_width / 100
      sprintf("|%s%s|", @bar_mark * len, " " *  (@bar_width - len))
    end

    def percentage(value = nil)
      if @total.zero?
        100
      else
        (value || @current) * 100 / @total
      end
    end

    def title
      @title[0,(@title_width - 1)] + ":"
    end

    def get_width
      # FIXME: I don't know how portable it is.
      default_width = 80
        #   begin
        #     tiocgwinsz = 0x5413
        #     data = [0, 0, 0, 0].pack("SSSS")
        #     if @out.ioctl(tiocgwinsz, data) >= 0 then
        #       rows, cols, xpixels, ypixels = data.unpack("SSSS")
        #       if cols >= 0 then cols else default_width end
        #     else
        #       default_width
        #     end
        #   rescue Exception
        #     default_width
        #   end
    end

    def show
      arguments = @format_arguments.map {|method| send(method) }
      line = sprintf(@format, *arguments)

      width = get_width
      if line.length == width - 1 
        @out.print(line + eol)
      elsif line.length >= width
        @bar_width = [@bar_width - (line.length - width + 1), 0].max
        if @bar_width == 0 then @out.print(line + eol) else show end
      else # line.length < width - 1
        @bar_width += width - line.length + 1
        show
      end
      @previous_time = Time.now
    end

    def show_progress
      if @total.zero?
        cur_percentage = 100
        prev_percentage = 0
      else
        cur_percentage  = (@current  * 100 / @total).to_i
        prev_percentage = (@previous * 100 / @total).to_i
      end

      if cur_percentage > prev_percentage || 
        Time.now - @previous_time >= 1 ||
        @is_finished
        show
      end
    end

  public
      def file_transfer_mode
      @format_arguments = [:title, :percentage, :bar, :stat_for_file_transfer]  
    end

    def format= (format)
      @format = format
    end

    def format_arguments= (arguments)
      @format_arguments = arguments
    end

    def finish
      @current = @total
      @is_finished = true
      show_progress
    end

    def halt
      @is_finished = true
      show_progress
    end

    def set (count)
      if count < 0 || count > @total
        raise "invalid count: #{count} (total: #{@total})"
      end
      @current = count
      show_progress
      @previous = @current
    end

    def inc (step = 1)
      @current += step
      @current = @total if @current > @total
      show_progress
      @previous = @current
    end

    def inspect
      "(ProgressBar: #{@current}/#{@total})"
    end
  end

  class CommandPattern
    class AbstractCommandError < Exception; end
    class UnknownCommandError < RuntimeError; end
    class CommandAlreadyExists < RuntimeError; end

    class << self
      def add(command)
        command = command.new if command.kind_of?(Class)

        @commands ||= {}
        if @commands.has_key?(command.name)
          raise CommandAlreadyExists
        else
          @commands[command.name] = command
        end

        if command.respond_to?(:altname)
          unless @commands.has_key?(command.altname)
            @commands[command.altname] = command
          end
        end
      end

      def <<(command)
        add(command)
      end

      attr_accessor :default
      def default=(command) #:nodoc:
        if command.kind_of?(CommandPattern)
        @default = command
        elsif command.kind_of?(Class)
          @default = command.new
        elsif @commands.has_key?(command)
          @default = @commands[command]
        else
          raise UnknownCommandError
        end
      end

      def command?(command)
        @commands.has_key?(command)
      end

      def command(command)
        if command?(command)
          @commands[command]
        else
          @default
        end
      end

      def [](cmd)
        self.command(cmd)
      end

      def default_ioe(ioe = {})
        ioe[:input]   ||= $stdin
        ioe[:output]  ||= $stdout
        ioe[:error]   ||= $stderr
        ioe
      end
    end

    def [](args, opts = {}, ioe = {})
      call(args, opts, ioe)
    end

    def name
      raise AbstractCommandError
    end

    def call(args, opts = {}, ioe = {})
      raise AbstractCommandError
    end

    def help
      raise AbstractCommandError
    end
  end

  class CommandHelp < CommandPattern
    def name
      "help"
    end

    def call(args, opts = {}, ioe = {})
      ioe = CommandPattern.default_ioe(ioe)

      help_on = args.shift

      if CommandPattern.command?(help_on)
        ioe[:output] << CommandPattern[help_on].help
      elsif help_on == "commands"
        ioe[:output] << <<-EOH
The commands known to minitar are:

    minitar create          Creates a new tarfile.
    minitar extract         Extracts files from a tarfile.
    minitar list            Lists files in the tarfile.

All commands accept the options --verbose and --progress, which are
mutually exclusive. In "minitar list", --progress means the same as
--verbose.

  --verbose, -V     Performs the requested command verbosely.
  --progress, -P    Shows a progress bar, if appropriate, for the action
                    being performed.

        EOH
      else
        ioe[:output] << "Unknown command: #{help_on}\n" unless help_on.nil? or help_on.empty?
        ioe[:output] << self.help
      end

      0
    end

    def help
      help = <<-EOH
This is a basic help message containing pointers to more information on
how to use this command-line tool. Try:

    minitar help commands       list all 'minitar' commands
    minitar help <COMMAND>      show help on <COMMAND>
                                  (e.g., 'minitar help create')
      EOH
    end
#   minitar add             Adds a file to an existing tarfile.
#   minitar delete          Deletes a file from an existing tarfile.
  end

  class CommandCreate < CommandPattern
    def name
      "create"
    end

    def altname
      "cr"
    end

    def call(args, opts = {}, ioe = {})
      argv    = []

      while (arg = args.shift)
        case arg
        when '--compress', '-z'
          opts[:compress] = true
        else
          argv << arg
        end
      end

      if argv.size < 2
        ioe[:output] << "Not enough arguments.\n\n"
        CommandPattern["help"][["create"]]
        return 255
      end

      output = argv.shift
      if '-' == output
        opts[:name] = "STDOUT"
        output = ioe[:output]
        opts[:output] = ioe[:error]
      else
        opts[:name] = output
        output = File.open(output, "wb")
        opts[:output] = ioe[:output]
      end

      if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:compress]
        output = Zlib::GzipWriter.new(output)
      end

      files = []
      if argv.include?("--")
          # Read stdin for the list of files.
        files = ""
        files << ioe[:input].read while not ioe[:input].eof?
        files = files.split(/\r\n|\n|\r/)
        args.delete("--")
      end

      files << argv.to_a
      files.flatten!

      if opts[:verbose]
        watcher = lambda do |action, name, stats|
          opts[:output] << "#{name}\n" if action == :dir or action == :file_done
        end
        finisher = lambda { opts[:output] << "\n" }
      elsif opts[:progress]
        progress = ProgressBar.new(opts[:name], 1)
        watcher = lambda do |action, name, stats|
          case action
          when :file_start, :dir
            progress.title = File.basename(name)
            if action == :dir
              progress.total += 1
              progress.inc
            else
              progress.total += stats[:size]
            end
          when :file_progress
            progress.inc(stats[:currinc])
          end
        end
        finisher = lambda do
          progress.title = opts[:name]
          progress.finish
        end
      else
        watcher = nil
        finisher = lambda { }
      end

      Archive::Tar::Minitar.pack(files, output, &watcher)
      finisher.call
      0
    ensure
      output.close if output and not output.closed?
    end

    def help
      help = <<-EOH
    minitar create [OPTIONS] <tarfile|-> <file|directory|-->+

Creates a new tarfile. If the tarfile is named .tar.gz or .tgz, then it
will be compressed automatically. If the tarfile is "-", then it will be
output to standard output (stdout) so that minitar may be piped.

The files or directories that will be packed into the tarfile are
specified after the name of the tarfile itself. Directories will be
processed recursively. If the token "--" is found in the list of files
to be packed, additional filenames will be read from standard input
(stdin). If any file is not found, the packaging will be halted.

create Options:
    --compress, -z  Compresses the tarfile with gzip.

      EOH
    end
  end

  class CommandExtract < CommandPattern
    def name
      "extract"
    end

    def altname
      "ex"
    end

    def call(args, opts = {}, ioe = {})
      argv    = []
      output  = nil
      dest    = "."
      files   = []

      while (arg = args.shift)
        case arg
        when '--uncompress', '-z'
          opts[:uncompress] = true
        when '--pipe'
          opts[:output] = ioe[:error]
          output = ioe[:output]
        when '--output', '-o'
          dest = args.shift
        else
          argv << arg
        end
      end

      if argv.size < 1
        ioe[:output] << "Not enough arguments.\n\n"
        CommandPattern["help"][["extract"]]
        return 255
      end

      input = argv.shift
      if '-' == input
        opts[:name] = "STDIN"
        input = ioe[:input]
      else
        opts[:name] = input
        input = File.open(input, "rb")
      end

      if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:uncompress]
        input = Zlib::GzipReader.new(input)
      end

      files << argv.to_a
      files.flatten!

      if opts[:verbose]
        watcher = lambda do |action, name, stats|
          opts[:output] << "#{name}\n" if action == :dir or action == :file_done
        end
        finisher = lambda { opts[:output] << "\n" }
      elsif opts[:progress]
        progress = ProgressBar.new(opts[:name], 1)
        watcher = lambda do |action, name, stats|
          case action
          when :file_start, :dir
            progress.title = File.basename(name)
            if action == :dir
              progress.total += 1
              progress.inc
            else
              progress.total += stats[:entry].size
            end
          when :file_progress
            progress.inc(stats[:currinc])
          end
        end
        finisher = lambda do
          progress.title = opts[:name]
          progress.finish
        end
      else
        watcher = nil
        finisher = lambda { }
      end

      if output.nil?
        Archive::Tar::Minitar.unpack(input, dest, files, &watcher)
        finisher.call
      else
        Archive::Tar::Minitar::Input.open(input) do |inp|
          inp.each do |entry|
            stats = {
              :mode     => entry.mode,
              :mtime    => entry.mtime,
              :size     => entry.size,
              :gid      => entry.gid,
              :uid      => entry.uid,
              :current  => 0,
              :currinc  => 0,
              :entry    => entry
            }

            if files.empty? or files.include?(entry.full_name)
              if entry.directory?
                puts "Directory: #{entry.full_name}"
                watcher[:dir, dest, stats] unless watcher.nil?
              else
                puts "File: #{entry.full_name}"
                watcher[:file_start, destfile, stats] unless watcher.nil?
                loop do
                  data = entry.read(4096)
                  break unless data
                  stats[:currinc] = output.write(data)
                  stats[:current] += stats[:currinc]

                  watcher[:file_progress, name, stats] unless watcher.nil?
                end
                watcher[:file_done, name, stats] unless watcher.nil?
              end
            end
          end
        end
      end

      0
    end

    def help
      help = <<-EOH
    minitar extract [OPTIONS] <tarfile|-> [<file>+]

Extracts files from an existing tarfile. If the tarfile is named .tar.gz
or .tgz, then it will be uncompressed automatically. If the tarfile is
"-", then it will be read from standard input (stdin) so that minitar
may be piped.

The files or directories that will be extracted from the tarfile are
specified after the name of the tarfile itself. Directories will be
processed recursively. Files must be specified in full. A file
"foo/bar/baz.txt" cannot simply be specified by specifying "baz.txt".
Any file not found will simply be skipped and an error will be reported.

extract Options:
    --uncompress, -z  Uncompresses the tarfile with gzip.
    --pipe            Emits the extracted files to STDOUT for piping.
    --output, -o      Extracts the files to the specified directory.

      EOH
    end
  end

  class CommandList < CommandPattern
    def name
      "list"
    end

    def altname
      "ls"
    end

    def modestr(mode)
      s = "---"
      s[0] = ?r if (mode & 4) == 4
      s[1] = ?w if (mode & 2) == 2
      s[2] = ?x if (mode & 1) == 1
      s
    end

    def call(args, opts = {}, ioe = {})
      argv    = []
      output  = nil
      dest    = "."
      files   = []
      opts[:field] = "name"

      while (arg = args.shift)
        case arg
        when '--sort', '-S'
          opts[:sort]   = true
          opts[:field]  = args.shift
        when '--reverse', '-R'
          opts[:reverse] = true
          opts[:sort]    = true
        when '--uncompress', '-z'
          opts[:uncompress] = true
        when '-l'
          opts[:verbose] = true
        else
          argv << arg
        end
      end

      if argv.size < 1
        ioe[:output] << "Not enough arguments.\n\n"
        CommandPattern["help"][["list"]]
        return 255
      end

      input = argv.shift
      if '-' == input
        opts[:name] = "STDIN"
        input = ioe[:input]
      else
        opts[:name] = input
        input = File.open(input, "rb")
      end

      if opts[:name] =~ /\.tar\.gz$|\.tgz$/ or opts[:uncompress]
        input = Zlib::GzipReader.new(input)
      end

      files << argv.to_a
      files.flatten!

      if opts[:verbose] or opts[:progress]
        format  = "%10s %4d %8s %8s %8d %12s %s"
        datefmt = "%b %d  %Y"
        timefmt = "%b %d %H:%M"
        fields  = %w(permissions inodes user group size date fullname)
      else
        format  = "%s"
        fields  = %w(fullname)
      end

      opts[:field] = opts[:field].intern
      opts[:field] = :full_name if opts[:field] == :name

      output = []

      Archive::Tar::Minitar::Input.open(input) do |inp|
        today = Time.now
        oneyear = Time.mktime(today.year - 1, today.month, today.day)
        inp.each do |entry|
          value = format % fields.map do |ff|
            case ff
            when "permissions"
              s = entry.directory? ? "d" : "-"
              s << modestr(entry.mode / 0100)
              s << modestr(entry.mode / 0010)
              s << modestr(entry.mode)
            when "inodes"
              entry.size / 512
            when "user"
              entry.uname || entry.uid || 0
            when "group"
              entry.gname || entry.gid || 0
            when "size"
              entry.size
            when "date"
              if Time.at(entry.mtime) > (oneyear)
                Time.at(entry.mtime).strftime(timefmt)
              else
                Time.at(entry.mtime).strftime(datefmt)
              end
            when "fullname"
              entry.full_name
            end
          end

          if opts[:sort]
            output << [entry.send(opts[:field]), value]
          else
            ioe[:output] << value << "\n"
          end

        end
      end

      if opts[:sort]
        output = output.sort { |a, b| a[0] <=> b[0] }
        if opts[:reverse]
          output.reverse_each { |oo| ioe[:output] << oo[1] << "\n" }
        else
          output.each { |oo| ioe[:output] << oo[1] << "\n" }
        end
      end

      0
    end

    def help
      help = <<-EOH
    minitar list [OPTIONS] <tarfile|-> [<file>+]

Lists files in an existing tarfile. If the tarfile is named .tar.gz or
.tgz, then it will be uncompressed automatically. If the tarfile is "-",
then it will be read from standard input (stdin) so that minitar may be
piped.

If --verbose or --progress is specified, then the file list will be
similar to that produced by the Unix command "ls -l".

list Options:
    --uncompress, -z      Uncompresses the tarfile with gzip.
    --sort [<FIELD>], -S  Sorts the list of files by the specified
                          field. The sort defaults to the filename.
    --reverse, -R         Reverses the sort.
    -l                    Lists the files in detail.

Sort Fields:
  name, mtime, size

      EOH
    end
  end

  CommandPattern << CommandHelp
  CommandPattern << CommandCreate
  CommandPattern << CommandExtract
  CommandPattern << CommandList
# CommandPattern << CommandAdd
# CommandPattern << CommandDelete

  def self.run(argv, input = $stdin, output = $stdout, error = $stderr)
    ioe = {
      :input  => input,
      :output => output,
      :error  => error,
    }
    opts = { }

    if argv.include?("--version")
      output << <<-EOB
minitar #{Archive::Tar::Minitar::VERSION}
  Copyright 2004 Mauricio Julio Ferna'ndez Pradier and Austin Ziegler
  This is free software with ABSOLUTELY NO WARRANTY.

  see http://rubyforge.org/projects/ruwiki for more information
      EOB
    end

    if argv.include?("--verbose") or argv.include?("-V")
      opts[:verbose]  = true
      argv.delete("--verbose")
      argv.delete("-V")
    end

    if argv.include?("--progress") or argv.include?("-P")
      opts[:progress] = true
      opts[:verbose]  = false
      argv.delete("--progress")
      argv.delete("-P")
    end

    command = CommandPattern[(argv.shift or "").downcase]
    command ||= CommandPattern["help"]
    return command[argv, opts, ioe]
  end
end