1#!/usr/bin/env python3

2

3 import os

4 import sys

5 import posixpath

6 import filecmp

7 import shutil

8

9 from argparse import ArgumentParser

10 from subprocess import Popen, PIPE, SubprocessError

11

12 DEFAULT_DIR = "/tmp/checkbox.optical"

13 DEFAULT_DEVICE_DIR = "device"

14 DEFAULT_IMAGE_DIR = "image"

15

16

17 CDROM_ID = "/lib/udev/cdrom_id"

18

19

20 def _command(command, shell=True):

21 proc = Popen(command, shell=shell, stdout=PIPE, stderr=PIPE)

22 return proc

23

24

25 def _command_out(command, shell=True):

26 proc = _command(command, shell)

27 return proc.communicate()[0].strip()

28

29

30 def compare_tree(source, target):

31 for dirpath, dirnames, filenames in os.walk(source):

32 # if both tree are empty return false

33 if dirpath == source and dirnames == [] and filenames == []:

34 return False

35 for name in filenames:

36 file1 = os.path.join(dirpath, name)

37 file2 = file1.replace(source, target, 1)

38 if os.path.isfile(file1) and not os.path.islink(file1):

39 if filecmp.cmp(file1, file2):

40 continue

41 else:

42 return False

43 else:

44 continue

45 return True

46

47

48 def read_test(device):

49 passed = False

50 device_dir = os.path.join(DEFAULT_DIR, DEFAULT_DEVICE_DIR)

51 image_dir = os.path.join(DEFAULT_DIR, DEFAULT_IMAGE_DIR)

52

53 for dir in (device_dir, image_dir):

54 if posixpath.exists(dir):

55 shutil.rmtree(dir)

56 os.makedirs(device_dir)

57

58 try:

59 _command("umount %s" % device).communicate()

60 mount = _command("mount -o ro %s %s" % (device, device_dir))

61 mount.communicate()

62 if mount.returncode != 0:

63 print(

64 "Unable to mount %s to %s" % (device, device_dir),

65 file=sys.stderr,

66 )

67 return False

68

69 file_copy = _command("cp -dpR %s %s" % (device_dir, image_dir))

70 file_copy.communicate()

71 if file_copy.returncode != 0:

72 print(

73 "Failed to copy files from %s to %s" % (device_dir, image_dir),

74 file=sys.stderr,

75 )

76 return False

77 if compare_tree(device_dir, image_dir):

78 passed = True

79 except (SubprocessError, OSError):

80 print(

81 "File Comparison failed while testing %s" % device, file=sys.stderr

82 )

83 passed = False

84 finally:

85 _command("umount %s" % device_dir).communicate(3)

86 for dir in (device_dir, image_dir):

87 if posixpath.exists(dir):

88 shutil.rmtree(dir)

89

90 if passed:

91 print("File Comparison passed (%s)" % device)

92

93 return passed

94

95

96 def get_capabilities(device):

97 cmd = "%s %s" % (CDROM_ID, device)

98 capabilities = _command_out(cmd)

99 return capabilities

100

101

102 def main():

103 tests = []

104 return_values = []

105

106 parser = ArgumentParser()

107 parser.add_argument(

108 "device",

109 nargs="+",

110 help=(

111 "Specify an optical device or list of devices "

112 "such as /dev/cdrom"

113 ),

114 )

115 args = parser.parse_args()

116

117 if os.geteuid() != 0:

118 parser.error("ERROR: Must be root to run this script.")

119

120 for device in args.device:

121

122 capabilities = get_capabilities(device)

123 if not capabilities:

124 print("Unable to get capabilities of %s" % device, file=sys.stderr)

125 return 1

126 for capability in capabilities.decode().split("\n"):

127 if capability[:3] == "ID_":

128 cap = capability[3:-2]

129 if cap == "CDROM" or cap == "CDROM_DVD":

130 tests.append("read")

131

132 for test in set(tests):

133 print("Testing %s on %s ... " % (test, device), file=sys.stdout)

134 tester = "%s_test" % test

135 return_values.append(globals()[tester](device))

136

137 return False in return_values

138

139

140 if __name__ == "__main__":

141 sys.exit(main())