Change all hashbangs
[time-slider.git] / usr / share / time-slider / lib / time_slider / util.py
1 #!/usr/bin/python3
2 #
3 # CDDL HEADER START
4 #
5 # The contents of this file are subject to the terms of the
6 # Common Development and Distribution License (the "License").
7 # You may not use this file except in compliance with the License.
8 #
9 # You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 # or http://www.opensolaris.org/os/licensing.
11 # See the License for the specific language governing permissions
12 # and limitations under the License.
13 #
14 # When distributing Covered Code, include this CDDL HEADER in each
15 # file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 # If applicable, add the following below this CDDL HEADER, with the
17 # fields enclosed by brackets "[]" replaced with your own identifying
18 # information: Portions Copyright [yyyy] [name of copyright owner]
19 #
20 # CDDL HEADER END
21 #
22
23 import os
24 import subprocess
25 import sys
26 import syslog
27 import math
28 import gio
29 import logging
30
31 def run_command(command, raise_on_try=True):
32     """
33     Wrapper function around subprocess.Popen
34     Returns a tuple of standard out and stander error.
35     Throws a RunTimeError if the command failed to execute or
36     if the command returns a non-zero exit status.
37
38     Assume the output is UTF-8 encoded
39     """
40
41     debug("Trying to run command %s" % (command), True)
42     try:
43         p = subprocess.Popen(command,
44                              stdout=subprocess.PIPE,
45                              stderr=subprocess.PIPE,
46                              close_fds=True)
47         outdata,errdata = (x.decode('utf-8') for x in p.communicate())
48         err = p.wait()
49     except OSError as message:
50         raise RuntimeError("%s subprocess error:\n %s" % \
51                             (command, str(message)))
52     if err != 0 and raise_on_try:
53         raise RuntimeError('%s failed with exit code %d\n%s' % \
54                             (str(command), err, errdata))
55     return outdata,errdata
56
57 def debug(message, verbose):
58     """
59     Prints message out to standard error and syslog if
60     verbose = True.
61     Note that the caller needs to first establish a syslog
62     context using syslog.openlog()
63     """
64     if verbose:
65         logging.getLogger('time-slider').debug(message)
66
67 def log_error(loglevel, message):
68     """
69     Trivial syslog wrapper that also outputs to stderr
70     Requires caller to have first opened a syslog session
71     using syslog.openlog()
72     """
73     logging.getLogger('time-slider').error(message)
74
75 def get_filesystem_capacity(path):
76     """Returns filesystem space usage of path as an integer percentage of
77        the entire capacity of path.
78     """
79     if not os.path.exists(path):
80         raise ValueError("%s is a non-existent path" % path)
81     f = os.statvfs(path)
82
83     unavailBlocks = f.f_blocks - f.f_bavail
84     capacity = int(math.ceil(100 * (unavailBlocks / float(f.f_blocks))))
85
86     return capacity
87
88 def get_available_size(path):
89     """Returns the available space in bytes under path"""
90     if not os.path.exists(path):
91         raise ValueError("%s is a non-existent path" % path)
92     f = os.statvfs(path)
93     free = int(f.f_bavail * f.f_frsize)
94
95     return free
96
97 def get_used_size(path):
98     """Returns the used space in bytes of fileystem associated
99        with path"""
100     if not os.path.exists(path):
101         raise ValueError("%s is a non-existent path" % path)
102     f = os.statvfs(path)
103
104     unavailBlocks = f.f_blocks - f.f_bavail
105     used = int(unavailBlocks * f.f_frsize)
106
107     return used
108
109 def get_total_size(path):
110     """Returns the total storage space in bytes of fileystem
111        associated with path"""
112     if not os.path.exists(path):
113         raise ValueError("%s is a non-existent path" % path)
114     f = os.statvfs(path)
115     total = int(f.f_blocks * f.f_frsize)
116
117     return total
118
119 def path_to_volume(path):
120     """
121        Tries to map a given path name to a gio Volume and
122        returns the gio.Volume object the enclosing
123        volume.
124        If it fails to find an enclosing volume it returns
125        None
126     """
127     gFile = gio.File(path)
128     try:
129         mount = gFile.find_enclosing_mount()
130     except gio.Error:
131         return None
132     else:
133         if mount != None:
134             volume = mount.get_volume()
135             return volume
136     return None