MythTV  master
fs_util.py
Go to the documentation of this file.
1 #
2 # fs_util.py - misc. routines not categorized in other modules
3 #
4 # Copyright 2008 Mike McGrath
5 # This file incorporates work covered by the following copyright
6 # Copyright 2006-2007 Red Hat, Inc.
7 #
8 # This copyrighted material is made available to anyone wishing to use, modify,
9 # copy, or redistribute it subject to the terms and conditions of the GNU
10 # General Public License v.2. This program is distributed in the hope that it
11 # will be useful, but WITHOUT ANY WARRANTY expressed or implied, including the
12 # implied warranties of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 # See the GNU General Public License for more details.
14 #
15 # You should have received a copy of the GNU General Public License along with
16 # this program; if not, write to the Free Software Foundation, Inc., 51
17 # Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. Any Red Hat
18 # trademarks that are incorporated in the source code or documentation are not
19 # subject to the GNU General Public License and may only be used or replicated
20 # with the express permission of Red Hat, Inc.
21 #
22 
23 from builtins import object
24 import os
25 
26 # We cache the contents of /etc/mtab ... the following variables are used
27 # to keep our cache in sync
28 mtab_mtime = None
29 mtab_map = []
30 
31 class MntEntObj(object):
32  mnt_fsname = None #* name of mounted file system */
33  mnt_dir = None #* file system path prefix */
34  mnt_type = None #* mount type (see mntent.h) */
35  mnt_opts = None #* mount options (see mntent.h) */
36  mnt_freq = 0 #* dump frequency in days */
37  mnt_passno = 0 #* pass number on parallel fsck */
38 
39  def __init__(self,input=None):
40  if input and isinstance(input, str):
41  (self.mnt_fsname, self.mnt_dir, self.mnt_type, self.mnt_opts, \
42  self.mnt_freq, self.mnt_passno) = input.split()
43  def __dict__(self):
44  return {"mnt_fsname": self.mnt_fsname, "mnt_dir": self.mnt_dir, \
45  "mnt_type": self.mnt_type, "mnt_opts": self.mnt_opts, \
46  "mnt_freq": self.mnt_freq, "mnt_passno": self.mnt_passno}
47  def __str__(self):
48  return "%s %s %s %s %s %s" % (self.mnt_fsname, self.mnt_dir, self.mnt_type, \
49  self.mnt_opts, self.mnt_freq, self.mnt_passno)
50 
51 class FileSystem(object):
52  def __init__(self, mntent):
53  self.mnt_dev = mntent.mnt_fsname
54  self.mnt_pnt = mntent.mnt_dir
55  self.fs_type = mntent.mnt_type
56  try:
57  stat_res = os.statvfs('%s' % self.mnt_pnt)
58  except OSError:
59  stat_res = self.f_bsize = self.f_frsize = self.f_blocks = self.f_blocks = self.f_bfree = self.f_bavail = self.f_files = self.f_ffree = self.f_favail = "UNKNOWN"
60  else:
61  self.f_bsize = stat_res.f_bsize
62  self.f_frsize = stat_res.f_frsize
63  self.f_blocks = stat_res.f_blocks
64  self.f_bfree = stat_res.f_bfree
65  self.f_bavail = stat_res.f_bavail
66  self.f_files = stat_res.f_files
67  self.f_ffree = stat_res.f_ffree
68  self.f_favail = stat_res.f_favail
69 
70  def to_dict(self):
71  return dict(mnt_pnt=self.mnt_pnt, fs_type=self.fs_type, f_favail=self.f_favail,
72  f_bsize=self.f_bsize, f_frsize=self.f_frsize, f_blocks=self.f_blocks,
73  f_bfree=self.f_bfree, f_bavail=self.f_bavail, f_files=self.f_files,
74  f_ffree=self.f_ffree)
75 
76  def __str__(self):
77  return "%s %s %s %s %s %s %s %s %s %s %s" % \
78  (self.mnt_dev, self.mnt_pnt, self.fs_type,
79  self.f_bsize, self.f_frsize, self.f_blocks,
80  self.f_bfree, self.f_bavail, self.f_files,
81  self.f_ffree, self.f_favail)
82 
83 
84 
85 def get_mtab(mtab="/proc/mounts", vfstype=None):
86  global mtab_mtime, mtab_map
87 
88  mtab_stat = os.stat(mtab)
89  if mtab_stat.st_mtime != mtab_mtime:
90  #print '''cache is stale ... refresh'''
91  mtab_mtime = mtab_stat.st_mtime
92  mtab_map = __cache_mtab__(mtab)
93 
94  # was a specific fstype requested?
95  if vfstype:
96  return [ent for ent in mtab_map if ent.mnt_type == vfstype]
97 
98  return mtab_map
99 
101  return [FileSystem(mnt) for mnt in get_mtab()]
102 
103 def __cache_mtab__(mtab="/proc/mounts"):
104  global mtab_mtime
105 
106  f = open(mtab)
107  #don't want empty lines
108  mtab = [MntEntObj(line) for line in f.read().split('\n') if len(line) > 0]
109  f.close()
110 
111  return mtab
112 
114  '''What this function attempts to do is take a file and return:
115  - the device the file is on
116  - the path of the file relative to the device.
117  For example:
118  /boot/vmlinuz -> (/dev/sda3, /vmlinuz)
119  /boot/efi/efi/redhat/elilo.conf -> (/dev/cciss0, /elilo.conf)
120  /etc/fstab -> (/dev/sda4, /etc/fstab)
121  '''
122 
123  # resolve any symlinks
124  fname = os.path.realpath(fname)
125 
126  # convert mtab to a dict
127  mtab_dict = {}
128  for ent in get_mtab():
129  mtab_dict[ent.mnt_dir] = ent.mnt_fsname
130 
131  # find a best match
132  fdir = os.path.dirname(fname)
133  match = fdir in mtab_dict
134  while not match:
135  fdir = os.path.realpath(os.path.join(fdir, os.path.pardir))
136  match = fdir in mtab_dict
137 
138  # construct file path relative to device
139  if fdir != os.path.sep:
140  fname = fname[len(fdir):]
141 
142  return (mtab_dict[fdir], fname)
143 
def get_mtab(mtab="/proc/mounts", vfstype=None)
Definition: fs_util.py:85
def __init__(self, mntent)
Definition: fs_util.py:52
def __init__(self, input=None)
Definition: fs_util.py:39
def get_file_device_path(fname)
Definition: fs_util.py:113
def __cache_mtab__(mtab="/proc/mounts")
Definition: fs_util.py:103