Skip to content

Instantly share code, notes, and snippets.

@alyssonbruno
Last active May 6, 2023 23:03
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save alyssonbruno/2976727 to your computer and use it in GitHub Desktop.
Save alyssonbruno/2976727 to your computer and use it in GitHub Desktop.
Make a clone of one file or device. Emule the command dd, without type conversion
import io
import mmap
from typing import Optional
_DEFAULTBS=io.DEFAULT_BUFFER_SIZE
def clone(input_file: Optional[str]='/dev/zero', output_file: Optional[str]='/dev/null', block_size: Optional[int]=_DEFAULTBS, count: Optional[int]=None, verbose: Optional[bool]=False):
"""Make a clone of one file or device. Emule the command dd, without type conversion
>>> clone(output_file='/tmp/swap.img',bs=512,count=8*2*1024*1024*1024)
True
>>> clone(input_file='/dev/sde',output_file='/tmp/pendrive.clone',block_size=1024,count=7969178)
True
>>> clone(output_file='/dev/sde',input_file='/tmp/pendrive.clone')
True
>>> clone('/dev/xpto','/tmp/pendrive.clone',512,7969178)
False
"""
try:
_count = int(count) if count else -1
_step = 0
with io.open(file=input_file,mode='r+b',buffering=0) as _if:
mm_in = mmap.mmap(_if.fileno(),block_size*_count if _count > 0 else 0)
with io.open(file=output_file,mode='wb',buffering=0) as _of:
_data = True
while _count and _data:
_data = mm_in.read(block_size)
_of.write(_data)
_count -=1
_step += 1
if verbose:
print(f'Step {_step}: data size {block_size} bytes')
mm_in.close()
return True
except Exception as e:
if verbose:
print(f'Error: {e}')
return False
if __name__ == '__main__':
from argparse import ArgumentParser
parser = ArgumentParser(prog='clone.py', description='clone a file or device')
parser.add_argument('-i', '--input', type=str, default='/dev/zero')
parser.add_argument('-o', '--output', type=str, default='/dev/null')
parser.add_argument('-b', '--block-size', type=int, default=_DEFAULTBS)
parser.add_argument('-c', '--count', type=int, default=None)
parser.add_argument('-v', '--verbose', action='store_true')
args = parser.parse_args()
if args.verbose:
print(args)
clone(input_file=args.input, output_file=args.output, block_size=args.block_size, count=args.count, verbose=args.verbose)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment