From: Arno Wagner <arno@wagner.name>
To: dm-crypt@saout.de
Subject: Re: [dm-crypt] How to find out about mapped device name?
Date: Tue, 5 Feb 2013 01:42:22 +0100 [thread overview]
Message-ID: <20130205004222.GA8339@tansi.org> (raw)
In-Reply-To: <CAADET=fQxTNEBFz4wfF-OKgsxHz46W=hEOLG9ojd4i3Smvgwbw@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 937 bytes --]
Attached is a Python-script I wrote some time ago, that
traverses /dev/mapper/* and finds all the relevant information,
including mount-point (or absence of).
Arno
On Mon, Feb 04, 2013 at 03:32:21PM -0800, David Li wrote:
> Hi Experts,
>
> I have already called luksFormat on a raw block dev and luksOpen to set up
> mapped device in /dev/mapper. Is there a command to find out about the
> mapping between the raw dev and mapped dev?
> _______________________________________________
> dm-crypt mailing list
> dm-crypt@saout.de
> http://www.saout.de/mailman/listinfo/dm-crypt
--
Arno Wagner, Dr. sc. techn., Dipl. Inform., Email: arno@wagner.name
GnuPG: ID: CB5D9718 FP: 12D6 C03B 1B30 33BB 13CF B774 E35C 5FA1 CB5D 9718
----
One of the painful things about our time is that those who feel certainty
are stupid, and those with any imagination and understanding are filled
with doubt and indecision. -- Bertrand Russell
[-- Attachment #2: cstat --]
[-- Type: text/plain, Size: 7143 bytes --]
#!/usr/bin/python
# cryptstat.py
# Displays all matching devices in /dev/ for a cryptsetup target
# Calls "cryptsetup status <target>" to get the initial info,
# then determines major/minor of the reported device and does
# a traversal of /dev/ to find all matches.
# Reports an augemented result of "cryptsetup status", also
# including mount points.
# Arguments are any number of cryptsetup targets. Does a validity
# check and refuses targets not found in /dev/mapper/
# Without argument, displays info on all targets found in /dev/mapper/
# (c) Arno Wagner 2010, distributed under the modified BSD license.
# Version 0.03
# Version history
# 0.03 Adjustments for cryptsrtup 1.2.0
# 0.02 fixed error on unmounted but mapped devices
import sys, os, stat, subprocess, re
dev_path = '/dev'
mapper_path = '/dev/mapper'
cryptsetup_path = '/usr/sbin/cryptsetup'
# IEC function
def str_iec(v):
n = float(v)
if n < 0 :
raise ValueError, 'Argument of str_iec() must not be negative'
prefix = ' ' # Actually the postfix of the output, but the
# prefix of the unit, if one is attached.
if n < 1024:
pass
elif n < 1024 * 1024:
n = n / 1024
prefix = 'ki'
elif n < 1024 * 1024 * 1024:
n = n / ( 1024 * 1024 )
prefix = 'Mi'
elif n < 1024 * 1024 * 1024 * 1024:
n = n / ( 1024 * 1024 * 1024 )
prefix = 'Gi'
elif n < 1024 * 1024 * 1024 * 1024 * 1024:
n = n / ( 1024 * 1024 * 1024 * 1024 )
prefix = 'Ti'
elif n < 1024 * 1024 * 1024 * 1024 * 1024 * 1024:
n = n / ( 1024 * 1024 * 1024 * 1024 * 1024 )
prefix = 'Ei'
else:
raise ValueError, 'Argument of str_iec() larger than (2^50)-1'
s = "%(n)5.1f " % {'n': n}
s = s + prefix
return s
# Utility functions
def normalize_path(path):
"""Replaces any number of occurences of '/' with a single '/'"""
# Note: INefficient, but should not matter
while path.find('//') > -1:
path = path.replace('//','/')
return(path)
def dir_walk(dir):
"""Returns a list of all filenames with full paths
(including dirs, specials, etc.) below the argument.
"." and ".." are omitted. Does not follow symblinks
to avoid loops, but there is no real loop prevention."""
names = []
dir = normalize_path(dir)
# process current directory
current = os.listdir(dir)
for d in current:
d = dir + '/' + d
# Test whether d is a directory. If so, recurse.
s = os.lstat(d)
if stat.S_ISDIR( s[stat.ST_MODE] ):
names.extend(dir_walk(d))
else:
names.append(d)
return(names)
def dir_walk_block(dir):
"""Returns the names of all block devices in the subtree at dir"""
names = dir_walk(dir)
block_dev = []
for n in names:
if stat.S_ISBLK(os.lstat(n)[stat.ST_MODE]):
block_dev.append(n)
return(block_dev)
def special_dev_major_minor(n):
"""Returns (major,minor) for a device special file name"""
s = os.lstat(n)
if not stat.S_ISBLK(s[stat.ST_MODE]) and \
not stat.S_ISCHR(s[stat.ST_MODE]) :
return None
else:
maj = os.major(s.st_rdev)
min = os.minor(s.st_rdev)
return (maj, min)
def build_block_major_minor_tables(dir):
"""Returns
1) a table of filenames that are all block special files
2) a dict mapping each name to (major,minor)
3) a dict mapping each (major,minor) pair to a table of filenames"""
names = []
name2pair = {}
pair2name = {}
names = dir_walk_block(dir)
for n in names:
maj, min = special_dev_major_minor(n)
name2pair[n] = (maj, min)
if (maj, min) not in pair2name:
pair2name[(maj, min)] = [n]
else:
pair2name[(maj, min)].append(n)
return (names, name2pair, pair2name)
# Start of main action
# determine list of targets to be processed
targets = []
# first get all in mapper_path except 'control'
mapper_targets = []
mapper_entries = os.listdir(mapper_path)
tmp = []
for e in mapper_entries:
if e != 'control':
tmp.append(e)
mapper_entries = tmp
# if argument list empty, copy mapper_entries
if len(sys.argv) == 1:
targets = mapper_entries
targets.sort()
else:
targets = sys.argv[1:]
# Make sure all targets are in mapper_entries
tbl = {}
for e in mapper_entries:
tbl[e] = None
for e in targets:
if e not in tbl:
print '\nError: Command argument "'+e+'" is not present in '+\
'mapper dir '+mapper_path+'!\nAborting\n'
sys.exit(1)
# print targets
# Create mappings (major,minor) <-> name
names, name2pair, pair2names = build_block_major_minor_tables(dev_path)
print
for t in targets:
# do call to "cryptsetup status"
cmd = cryptsetup_path + ' status ' + t
# print 'calling "' + cmd + '"'
p = subprocess.Popen(cmd, shell=True, bufsize=0,
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, close_fds=True)
(out, err) = p.communicate()
out_lines = out.splitlines()
if (p.returncode != 0): raise IOError(p.returncode, err)
# print('command output = [' + out + ']')
# check output line 7 for ' device: <device name>'
if not re.match('\ \ device\:\ \ \S+', out_lines[4]):
print '\nError: Line 7 of cryptsetup output has unexpected form'
print 'Expected: " device: <device name>'
print 'found: [' + out_lines[4]+ ']'
print 'complete cryptsetup output:\m'
print out
print '\nAborting!\n'
sys.exit(1)
device = out_lines[4][11:]
# print 'device found: [' + device + ']'
(maj, min) = name2pair[device]
# print '(maj, min) = ', (maj, min)
devices = pair2names[(maj, min)]
dev_str = ''
for d in devices: dev_str = dev_str + d + ' '
# print 'devices: ', dev_str
out_lines[4] = ' devices: '+str((maj, min))+' '+dev_str
for l in out_lines:
if re.match('\s+size:\s+(\d+)\ssectors.*', l):
m = re.match('\s+size:\s+(\d+)\ssectors.*', l)
s = int(m.group(1))
l = l.rstrip('\n')
print l + ' ( '+ str_iec(s * 512) + ' Bytes )'
else:
print l
# determine mounts and print them
mounts = ' mounted:'
# ';echo' in next command is so that we have at least one line
# of output to avoid an error from subprocess
cmd = 'mount | grep '+mapper_path+'/'+t+'; echo'
# print 'calling "' + cmd + '"'
p = subprocess.Popen(cmd, shell=True, bufsize=0,
stdin=subprocess.PIPE, stdout=subprocess.PIPE,
stderr=subprocess.PIPE, close_fds=True)
(out, err) = p.communicate()
out_lines = out.splitlines()
# print('command output = [' + out + ']')
if (p.returncode != 0): raise IOError(p.returncode, err)
if len(out_lines) == 1:
mounts = mounts + ' not mounted'
else:
for l in out_lines:
# print 'l = ', l
match = re.search(' on (\S+) type', l)
if match != None:
mounts = mounts + ' ' + match.group(1)
print mounts
print
prev parent reply other threads:[~2013-02-05 0:42 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-02-04 23:32 [dm-crypt] How to find out about mapped device name? David Li
2013-02-04 23:50 ` .. ink ..
2013-02-04 23:57 ` David Li
2013-02-05 0:08 ` .. ink ..
2013-02-05 0:30 ` Robert Nichols
2013-02-05 2:24 ` Milan Broz
2013-02-05 17:57 ` David Li
2013-02-05 0:42 ` Arno Wagner [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130205004222.GA8339@tansi.org \
--to=arno@wagner.name \
--cc=dm-crypt@saout.de \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.