#!/usr/bin/env python import commands import os import os.path import sys # Location of the DPKG files dpkg_dir = '/var/lib/dpkg' # Global variables name_lookup = {} rootfs_id = '' # Read in the full display names for packages def read_names(): global dpkg_dir global name_lookup pkg = '' # Read though the DPKG status file pkg_stat = open(dpkg_dir + '/status', 'r') for line in pkg_stat: line = line.rstrip() # Extract the package name and display name if line[0:8] == 'Package:': pkg = line[9:] elif line[0:19] == 'Maemo-Display-Name:': # Only store the display name if it's different full_name = line[20:] if pkg != full_name: name_lookup[pkg] = full_name pkg_stat.close() # Lookup the full display name for a package def get_name(pkg): global name_lookup # Check whether a full display name exists for this package if name_lookup.has_key(pkg): return name_lookup[pkg] return # Return the filesystem ID for the specified file/directory def get_fsid(file): return os.stat(file).st_dev # Check whether the specified file is on the rootfs or not def is_rootfs(file): global rootfs_id global rootfs_pkg # Store the rootfs ID if it hasn't yet been set if rootfs_id == '': rootfs_id = get_fsid('/') # Check whether the filesystem ID matches that of the rootfs if get_fsid(file) == rootfs_id: return 1 return 0 # Find the on-disk usage of a file def disk_usage(file, seen): # Run stat on the file stat = os.stat(file) inode = stat.st_ino if seen.has_key(inode): return seen[inode] = 1 blksize = stat.st_blksize # Block size for the disk chunknum = stat.st_blocks # Number of 512b blocks used by file blk_mult = blksize / 512 # How many 512b chunks are in one block # Work out how many blocks the file is actually using blk_count = (chunknum + blk_mult - 1) / blk_mult # Return the size in kb return blk_count * blksize / 1024 # Lookup the sizes for a given package def get_size(pkg, list = 0): global dpkg_dir # Open the packages .list file try: pkg_info = open(dpkg_dir + '/info/' + pkg + '.list', 'r') dulist = {} seen = {} # Read through and store the paths for files on the rootfs for file in pkg_info: file = file.rstrip() if not os.path.isfile(file): continue if os.path.islink(file): continue if not is_rootfs(file): continue # Lookup the disk usage of the file size = disk_usage(file, seen) if size is None: continue if size == 0: continue dulist[file] = size except IOError: return finally: pkg_info.close() # Check whether there are any files on the rootfs if len(dulist) == 0: return # Return either the total size or the list of individual file sizes if list == 0: return sum(dulist.values()) else: return dulist # Get the total rootfs size for all non-l10n packages def checkpkgs(): # Store the display names for later lookup read_names() # Loop through all files in the DPKG info directory for file in os.listdir(dpkg_dir + '/info'): # Skip any that aren't .list files if file[-5:] != '.list': continue # Skip the l10n packages if file.find('l10n') > -1: continue # Extract the package name pkg = file[0:len(file) - 5] # Lookup the package rootfs size size = get_size(pkg) # Skip further processing if there's no rootfs usage if size is None: continue # Lookup the package's display name name = get_name(pkg) # If there is one, append it in brackets if not name is None: pkg = pkg + ' (' + name + ')' # Output the package size and name print '%d\t%s' % (size, pkg) # List the rootfs files in the given package (and their sizes) def pkglist(pkg): # Lookup the array of files and sizes sizes = get_size(pkg, 1) # Output the info if not sizes is None: for (file, size) in sizes.items(): print "%d\t%s" % (size, file) # Report the total rootfs usage for the given package def pkgsize(pkg): # Lookup the rootfs usage size = get_size(pkg) # Report the rootfs usage (or 0 if there is none) if size is None: print '0\t%s' % pkg else: print '%d\t%s' % (size, pkg) # Use the first parameter as the command to run. if sys.argv[1] == 'checkpkgs': checkpkgs() elif sys.argv[1] == 'pkglist': pkglist(sys.argv[2]) elif sys.argv[1] == 'pkgsize': pkgsize(sys.argv[2]) # vim: ts=4 et