adlr@google.com | 1c98ef4 | 2009-10-28 00:00:13 +0000 | [diff] [blame^] | 1 | #!/usr/bin/env python |
| 2 | |
| 3 | # This program operates much like dd, but with two important differences: |
| 4 | # 1. Many features lacking |
| 5 | # 2. seek_bytes= param can specify seek offset in bytes, not block size |
| 6 | |
| 7 | import os |
| 8 | import sys |
| 9 | import time |
| 10 | |
| 11 | def parseNumber(numstr): |
| 12 | if numstr.endswith("GB"): |
| 13 | return int(numstr[:-2]) * 1000 * 1000 * 1000 |
| 14 | if numstr.endswith("MB"): |
| 15 | return int(numstr[:-2]) * 1000 * 1000 |
| 16 | if numstr.endswith("kB"): |
| 17 | return int(numstr[:-2]) * 1000 |
| 18 | if numstr.endswith("G"): |
| 19 | return int(numstr[:-1]) * 1024 * 1024 * 1024 |
| 20 | if numstr.endswith("M"): |
| 21 | return int(numstr[:-1]) * 1024 * 1024 |
| 22 | if numstr.endswith("K"): |
| 23 | return int(numstr[:-1]) * 1024 |
| 24 | if numstr.endswith("b"): |
| 25 | return int(numstr[:-1]) * 512 |
| 26 | if numstr.endswith("w"): |
| 27 | return int(numstr[:-1]) * 2 |
| 28 | if numstr.endswith("c"): |
| 29 | return int(numstr[:-1]) |
| 30 | if not numstr.isdigit(): |
| 31 | print >> sys.stderr, "Don't know how to parse number", numstr |
| 32 | sys.exit(1) |
| 33 | return int(numstr) |
| 34 | |
| 35 | def main(argv): |
| 36 | arg_if = "" |
| 37 | arg_of = "" |
| 38 | arg_bs = 512 |
| 39 | arg_seek = -1 |
| 40 | arg_seek_bytes = -1 |
| 41 | |
| 42 | for i in argv: |
| 43 | if i.startswith("if="): |
| 44 | arg_if=i[3:] |
| 45 | elif i.startswith("of="): |
| 46 | arg_of=i[3:] |
| 47 | elif i.startswith("bs="): |
| 48 | arg_bs=parseNumber(i[3:]) |
| 49 | elif i.startswith("seek="): |
| 50 | arg_seek=int(i[5:]) |
| 51 | elif i.startswith("seek_bytes="): |
| 52 | arg_seek_bytes=parseNumber(i[11:]) |
| 53 | |
| 54 | if arg_seek >= 0 and arg_seek_bytes >= 0: |
| 55 | print >> sys.stderr, "you can't specify seek= and seek_bytes=" |
| 56 | sys.exit(1) |
| 57 | |
| 58 | seek_bytes = 0 |
| 59 | if arg_seek >= 0: |
| 60 | seek_bytes = arg_seek * arg_bs |
| 61 | elif arg_seek_bytes >= 0: |
| 62 | seek_bytes = arg_seek_bytes |
| 63 | |
| 64 | if_fd = 0 |
| 65 | of_fd = 1 |
| 66 | if len(arg_if) != 0: |
| 67 | print >> sys.stderr, "opening for read", arg_if |
| 68 | if_fd = os.open(arg_if, os.O_RDONLY) |
| 69 | if len(arg_of) != 0: |
| 70 | print >> sys.stderr, "opening for write", arg_of |
| 71 | of_fd = os.open(arg_of, os.O_WRONLY | os.O_TRUNC | os.O_CREAT) |
| 72 | |
| 73 | if arg_seek_bytes > 0: |
| 74 | print >> sys.stderr, "seeking to", seek_bytes, "bytes in output file" |
| 75 | os.lseek(of_fd, seek_bytes, os.SEEK_SET) |
| 76 | |
| 77 | bytes_copied = 0 |
| 78 | |
| 79 | t1 = time.time() |
| 80 | |
| 81 | buf = os.read(if_fd, arg_bs) |
| 82 | while len(buf) > 0: |
| 83 | bytes_written = 0 |
| 84 | while bytes_written < len(buf): |
| 85 | bytes_written += os.write(of_fd, buf[bytes_written:]) |
| 86 | bytes_copied += bytes_written |
| 87 | buf = os.read(if_fd, arg_bs) |
| 88 | |
| 89 | t2 = time.time() |
| 90 | |
| 91 | os.close(if_fd) |
| 92 | os.close(of_fd) |
| 93 | |
| 94 | # print timing info |
| 95 | print >> sys.stderr, 'copy %d bytes took %0.3f s' % (bytes_copied, t2 - t1) |
| 96 | print >> sys.stderr, 'speed: %0.1f MB/s' % \ |
| 97 | ((bytes_copied / 1000000) / (t2 - t1)) |
| 98 | |
| 99 | if __name__ == '__main__': |
| 100 | main(sys.argv) |