|
1 #!/usr/bin/python |
|
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 # Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved. |
|
24 |
|
25 import testutils |
|
26 if __name__ == "__main__": |
|
27 testutils.setup_environment("../../../proto") |
|
28 import pkg5unittest |
|
29 |
|
30 import errno |
|
31 import os |
|
32 import sys |
|
33 import traceback |
|
34 import unittest |
|
35 |
|
36 import pkg.altroot as ar |
|
37 import pkg.client.image as image |
|
38 |
|
39 class TestAltroot(pkg5unittest.CliTestCase): |
|
40 persistent_setup = True |
|
41 |
|
42 def setUp(self): |
|
43 self.i_count = 4 |
|
44 pkg5unittest.CliTestCase.setUp(self, image_count=self.i_count) |
|
45 |
|
46 # image path |
|
47 self.i = [] |
|
48 |
|
49 # image files and directories |
|
50 self.p_f1 = "f1" |
|
51 self.p_f2 = "f2" |
|
52 self.p_none = "none" |
|
53 self.p_d = "d" |
|
54 self.p_d_f1 = os.path.join(self.p_d, "f1") |
|
55 self.p_d_f2 = os.path.join(self.p_d, "f2") |
|
56 self.p_d_none = os.path.join(self.p_d, "none") |
|
57 self.p_f1_redir = "f1_redir" |
|
58 self.p_f2_redir = "f2_redir" |
|
59 self.p_d_redir = "d_redir" |
|
60 self.p_d_f1_redir = os.path.join(self.p_d_redir, "f1") |
|
61 self.p_d_f2_redir = os.path.join(self.p_d_redir, "f2") |
|
62 self.p_d_none_redir = os.path.join(self.p_d_redir, "none") |
|
63 |
|
64 for i in range(0, self.i_count): |
|
65 # first assign paths. we'll use the image paths even |
|
66 # though we're not actually doing any testing with |
|
67 # real images. |
|
68 r = self.img_path(i) |
|
69 self.i.insert(i, r) |
|
70 |
|
71 os.makedirs(r) |
|
72 if i == 0: |
|
73 # simulate a root image |
|
74 os.makedirs( |
|
75 os.path.join(r, image.img_user_prefix)) |
|
76 elif i == 1: |
|
77 # simulate a user image |
|
78 os.makedirs( |
|
79 os.path.join(r, image.img_root_prefix)) |
|
80 elif i == 2: |
|
81 # corrupt image: both root and user |
|
82 os.makedirs( |
|
83 os.path.join(r, image.img_user_prefix)) |
|
84 os.makedirs( |
|
85 os.path.join(r, image.img_root_prefix)) |
|
86 |
|
87 for i in range(0, self.i_count): |
|
88 r = self.i[i] |
|
89 if i > 0: |
|
90 r_alt = self.i[i - 1] |
|
91 else: |
|
92 r_alt = self.i[self.i_count - 1] |
|
93 r_redir = os.path.basename(r_alt) |
|
94 |
|
95 # create directories and files within the image |
|
96 self.make_file(os.path.join(r, self.p_f1), "foo") |
|
97 self.make_file(os.path.join(r, self.p_f2), "foo") |
|
98 self.make_file(os.path.join(r, self.p_d_f1), "bar") |
|
99 self.make_file(os.path.join(r, self.p_d_f2), "bar") |
|
100 |
|
101 # create sym links that point outside that image |
|
102 os.symlink(os.path.join("..", r_redir, self.p_f1), |
|
103 os.path.join(r, self.p_f1_redir)) |
|
104 |
|
105 os.symlink(os.path.join("..", r_redir, self.p_f2), |
|
106 os.path.join(r, self.p_f2_redir)) |
|
107 |
|
108 os.symlink(os.path.join("..", r_redir, self.p_d), |
|
109 os.path.join(r, self.p_d_redir)) |
|
110 |
|
111 def __eremote(self, func, args): |
|
112 e = None |
|
113 try: |
|
114 func(*args) |
|
115 except: |
|
116 e_type, e, e_traceback = sys.exc_info() |
|
117 |
|
118 if isinstance(e, OSError) and e.errno == errno.EREMOTE: |
|
119 return |
|
120 |
|
121 if e == None: |
|
122 e_str = str(None) |
|
123 else: |
|
124 e_str = traceback.format_exc() |
|
125 |
|
126 args = ", ".join([str(a) for a in args]) |
|
127 self.fail( |
|
128 "altroot call didn't return OSError EREMOTE exception\n" |
|
129 "call: %s(%s)\n" |
|
130 "exception: %s\n" % |
|
131 (func.__name__, args, e_str)) |
|
132 |
|
133 def test_ar_err_eremote(self): |
|
134 """Verify that all altroot accessor functions return EREMOTE |
|
135 if they traverse a path which contains a symlink that point |
|
136 somewhere outside the specified altroot namespace.""" |
|
137 |
|
138 r = self.i[0] |
|
139 invoke = [ |
|
140 (ar.ar_open, (r, self.p_f1_redir, os.O_RDONLY)), |
|
141 (ar.ar_open, (r, self.p_d_f1_redir, os.O_RDONLY)), |
|
142 |
|
143 (ar.ar_unlink, (r, self.p_d_f1_redir)), |
|
144 |
|
145 (ar.ar_rename, (r, self.p_d_f1_redir, self.p_d_f1)), |
|
146 (ar.ar_rename, (r, self.p_d_f1, self.p_d_f1_redir)), |
|
147 (ar.ar_rename, (r, self.p_d_f1_redir, self.p_d_f2_redir)), |
|
148 |
|
149 (ar.ar_mkdir, (r, self.p_d_none_redir, 0777)), |
|
150 |
|
151 (ar.ar_stat, (r, self.p_f1_redir)), |
|
152 (ar.ar_stat, (r, self.p_d_f1_redir)), |
|
153 |
|
154 (ar.ar_isdir, (r, self.p_d_redir)), |
|
155 (ar.ar_isdir, (r, self.p_d_f1_redir)), |
|
156 |
|
157 (ar.ar_exists, (r, self.p_f1_redir)), |
|
158 (ar.ar_exists, (r, self.p_d_redir)), |
|
159 (ar.ar_exists, (r, self.p_d_f1_redir)), |
|
160 |
|
161 (ar.ar_diff, (r, self.p_f1, self.p_f2_redir)), |
|
162 (ar.ar_diff, (r, self.p_f1_redir, self.p_f2)), |
|
163 (ar.ar_diff, (r, self.p_d_f1, self.p_d_f2_redir)), |
|
164 (ar.ar_diff, (r, self.p_d_f1_redir, self.p_d_f2)), |
|
165 ] |
|
166 for func, args in invoke: |
|
167 self.__eremote(func, args) |
|
168 |
|
169 def __bad_img_prefix(self, func, args): |
|
170 rv = func(*args) |
|
171 if rv == None: |
|
172 return |
|
173 |
|
174 args = ", ".join([str(a) for a in args]) |
|
175 self.fail( |
|
176 "altroot call didn't return None\n" |
|
177 "call: %s(%s)\n" |
|
178 "rv: %s\n" % |
|
179 (func.__name__, args, str(rv))) |
|
180 |
|
181 def test_ar_err_img_prefix(self): |
|
182 """Verify that ar_img_prefix() returns None if we have a |
|
183 corrupt image. image 2 has both user and root image |
|
184 repositories. image 3 is not an image, it's an empty |
|
185 directory.""" |
|
186 |
|
187 invoke = [ |
|
188 (ar.ar_img_prefix, (self.i[2],)), |
|
189 (ar.ar_img_prefix, (self.i[3],)), |
|
190 ] |
|
191 for func, args in invoke: |
|
192 self.__bad_img_prefix(func, args) |
|
193 |
|
194 if __name__ == "__main__": |
|
195 unittest.main() |