1#!/bin/sh
2# $FreeBSD: head/tools/regression/pjdfstest/tests/chown/00.t 228975 2011-12-30 00:04:11Z uqs $
3
4desc="chown changes ownership"
5
6dir=`dirname $0`
7. ${dir}/../misc.sh
8
9if supported lchmod; then
10	echo "1..1349"
11else
12	echo "1..1323"
13fi
14
15n0=`namegen`
16n1=`namegen`
17n2=`namegen`
18
19expect 0 mkdir ${n2} 0755
20cdir=`pwd`
21cd ${n2}
22
23# super-user can always modify ownership
24for type in regular dir fifo block char socket symlink; do
25	if [ "${type}" != "symlink" ]; then
26		create_file ${type} ${n0}
27
28		expect 0 chown ${n0} 123 456
29		expect 123,456 lstat ${n0} uid,gid
30		expect 0 chown ${n0} 0 0
31		expect 0,0 lstat ${n0} uid,gid
32
33		expect 0 symlink ${n0} ${n1}
34		uidgid=`${fstest} lstat ${n1} uid,gid`
35		expect 0 chown ${n1} 123 456
36		expect 123,456 stat ${n1} uid,gid
37		expect 123,456 stat ${n0} uid,gid
38		expect ${uidgid} lstat ${n1} uid,gid
39		expect 0 unlink ${n1}
40
41		if [ "${type}" = "dir" ]; then
42			expect 0 rmdir ${n0}
43		else
44			expect 0 unlink ${n0}
45		fi
46	fi
47
48	create_file ${type} ${n0}
49	expect 0 lchown ${n0} 123 456
50	expect 123,456 lstat ${n0} uid,gid
51	if [ "${type}" = "dir" ]; then
52		expect 0 rmdir ${n0}
53	else
54		expect 0 unlink ${n0}
55	fi
56done
57
58# non-super-user can modify file group if he is owner of a file and
59# gid he is setting is in his groups list.
60for type in regular dir fifo block char socket symlink; do
61	if [ "${type}" != "symlink" ]; then
62		create_file ${type} ${n0}
63
64		expect 0 chown ${n0} 65534 65533
65		expect 65534,65533 lstat ${n0} uid,gid
66		expect 0 -u 65534 -g 65532,65531 -- chown ${n0} -1 65532
67		expect 65534,65532 lstat ${n0} uid,gid
68		expect 0 -u 65534 -g 65532,65531 chown ${n0} 65534 65531
69		expect 65534,65531 lstat ${n0} uid,gid
70
71		expect 0 symlink ${n0} ${n1}
72		uidgid=`${fstest} lstat ${n1} uid,gid`
73		expect 0 chown ${n1} 65534 65533
74		expect 65534,65533 stat ${n0} uid,gid
75		expect 65534,65533 stat ${n1} uid,gid
76		expect ${uidgid} lstat ${n1} uid,gid
77		expect 0 -u 65534 -g 65532,65531 -- chown ${n1} -1 65532
78		expect 65534,65532 stat ${n0} uid,gid
79		expect 65534,65532 stat ${n1} uid,gid
80		expect ${uidgid} lstat ${n1} uid,gid
81		expect 0 -u 65534 -g 65532,65531 chown ${n1} 65534 65531
82		expect 65534,65531 stat ${n0} uid,gid
83		expect 65534,65531 stat ${n1} uid,gid
84		expect ${uidgid} lstat ${n1} uid,gid
85		expect 0 unlink ${n1}
86
87		if [ "${type}" = "dir" ]; then
88			expect 0 rmdir ${n0}
89		else
90			expect 0 unlink ${n0}
91		fi
92	fi
93
94	create_file ${type} ${n0}
95	expect 0 lchown ${n0} 65534 65533
96	expect 65534,65533 lstat ${n0} uid,gid
97	expect 0 -u 65534 -g 65532,65531 -- lchown ${n0} -1 65532
98	expect 65534,65532 lstat ${n0} uid,gid
99	expect 0 -u 65534 -g 65532,65531 lchown ${n0} 65534 65531
100	expect 65534,65531 lstat ${n0} uid,gid
101	if [ "${type}" = "dir" ]; then
102		expect 0 rmdir ${n0}
103	else
104		expect 0 unlink ${n0}
105	fi
106done
107
108# chown(2) return 0 if user is not owner of a file, but chown(2) is called
109# with both uid and gid equal to -1.
110for type in regular dir fifo block char socket symlink; do
111	if [ "${type}" != "symlink" ]; then
112		create_file ${type} ${n0}
113
114		expect 0 chown ${n0} 65534 65533
115		expect 0 -u 65532 -g 65531 -- chown ${n0} -1 -1
116		expect 65534,65533 stat ${n0} uid,gid
117
118		expect 0 symlink ${n0} ${n1}
119		uidgid=`${fstest} lstat ${n1} uid,gid`
120		expect 0 chown ${n1} 65534 65533
121		expect 65534,65533 stat ${n0} uid,gid
122		expect 65534,65533 stat ${n1} uid,gid
123		expect ${uidgid} lstat ${n1} uid,gid
124		expect 0 -u 65532 -g 65531 -- chown ${n0} -1 -1
125		expect 65534,65533 stat ${n0} uid,gid
126		expect 65534,65533 stat ${n1} uid,gid
127		expect ${uidgid} lstat ${n1} uid,gid
128		expect 0 unlink ${n1}
129
130		if [ "${type}" = "dir" ]; then
131			expect 0 rmdir ${n0}
132		else
133			expect 0 unlink ${n0}
134		fi
135	fi
136
137	create_file ${type} ${n0}
138	expect 0 lchown ${n0} 65534 65533
139	expect 0 -u 65532 -g 65531 -- lchown ${n0} -1 -1
140	expect 65534,65533 lstat ${n0} uid,gid
141	if [ "${type}" = "dir" ]; then
142		expect 0 rmdir ${n0}
143	else
144		expect 0 unlink ${n0}
145	fi
146done
147
148# when super-user calls chown(2), set-uid and set-gid bits may be removed.
149for type in regular dir fifo block char socket symlink; do
150	if [ "${type}" != "symlink" ]; then
151		create_file ${type} ${n0}
152
153		expect 0 chown ${n0} 65534 65533
154		expect 0 chmod ${n0} 06555
155		expect 06555,65534,65533 stat ${n0} mode,uid,gid
156		expect 0 chown ${n0} 65532 65531
157		expect "(06555|0555),65532,65531" stat ${n0} mode,uid,gid
158		expect 0 chmod ${n0} 06555
159		expect 06555,65532,65531 stat ${n0} mode,uid,gid
160		expect 0 chown ${n0} 0 0
161		expect "(06555|0555),0,0" stat ${n0} mode,uid,gid
162
163		expect 0 symlink ${n0} ${n1}
164		expect 0 chown ${n1} 65534 65533
165		expect 0 chmod ${n1} 06555
166		expect 06555,65534,65533 stat ${n0} mode,uid,gid
167		expect 06555,65534,65533 stat ${n1} mode,uid,gid
168		expect 0 chown ${n1} 65532 65531
169		expect "(06555|0555),65532,65531" stat ${n0} mode,uid,gid
170		expect "(06555|0555),65532,65531" stat ${n1} mode,uid,gid
171		expect 0 chmod ${n1} 06555
172		expect 06555,65532,65531 stat ${n0} mode,uid,gid
173		expect 06555,65532,65531 stat ${n1} mode,uid,gid
174		expect 0 chown ${n1} 0 0
175		expect "(06555|0555),0,0" stat ${n0} mode,uid,gid
176		expect "(06555|0555),0,0" stat ${n1} mode,uid,gid
177		expect 0 unlink ${n1}
178
179		if [ "${type}" = "dir" ]; then
180			expect 0 rmdir ${n0}
181		else
182			expect 0 unlink ${n0}
183		fi
184	fi
185
186	if [ "${type}" != "symlink" ] || supported lchmod; then
187		create_file ${type} ${n0}
188		expect 0 lchown ${n0} 65534 65533
189		if supported lchmod; then
190			expect 0 lchmod ${n0} 06555
191		else
192			expect 0 chmod ${n0} 06555
193		fi
194		expect 06555,65534,65533 lstat ${n0} mode,uid,gid
195		expect 0 lchown ${n0} 65532 65531
196		expect "(06555|0555),65532,65531" lstat ${n0} mode,uid,gid
197		if supported lchmod; then
198			expect 0 lchmod ${n0} 06555
199		else
200			expect 0 chmod ${n0} 06555
201		fi
202		expect 06555,65532,65531 lstat ${n0} mode,uid,gid
203		expect 0 lchown ${n0} 0 0
204		expect "(06555|0555),0,0" lstat ${n0} mode,uid,gid
205		if [ "${type}" = "dir" ]; then
206			expect 0 rmdir ${n0}
207		else
208			expect 0 unlink ${n0}
209		fi
210	fi
211done
212
213# when non-super-user calls chown(2) successfully, set-uid and set-gid bits may
214# be removed, except when both uid and gid are equal to -1.
215for type in regular dir fifo block char socket symlink; do
216	if [ "${type}" != "symlink" ]; then
217		create_file ${type} ${n0}
218
219		expect 0 chown ${n0} 65534 65533
220		expect 0 chmod ${n0} 06555
221		expect 06555,65534,65533 stat ${n0} mode,uid,gid
222		expect 0 -u 65534 -g 65533,65532 chown ${n0} 65534 65532
223		expect 0555,65534,65532 stat ${n0} mode,uid,gid
224		expect 0 chmod ${n0} 06555
225		expect 06555,65534,65532 stat ${n0} mode,uid,gid
226		expect 0 -u 65534 -g 65533,65532 -- chown ${n0} -1 65533
227		expect 0555,65534,65533 stat ${n0} mode,uid,gid
228		expect 0 chmod ${n0} 06555
229		expect 06555,65534,65533 stat ${n0} mode,uid,gid
230		expect 0 -u 65534 -g 65533,65532 -- chown ${n0} -1 -1
231		expect "(06555|0555),65534,65533" stat ${n0} mode,uid,gid
232
233		expect 0 symlink ${n0} ${n1}
234		expect 0 chown ${n1} 65534 65533
235		expect 0 chmod ${n1} 06555
236		expect 06555,65534,65533 stat ${n0} mode,uid,gid
237		expect 06555,65534,65533 stat ${n1} mode,uid,gid
238		expect 0 -u 65534 -g 65533,65532 chown ${n1} 65534 65532
239		expect 0555,65534,65532 stat ${n0} mode,uid,gid
240		expect 0555,65534,65532 stat ${n1} mode,uid,gid
241		expect 0 chmod ${n1} 06555
242		expect 06555,65534,65532 stat ${n0} mode,uid,gid
243		expect 06555,65534,65532 stat ${n1} mode,uid,gid
244		expect 0 -u 65534 -g 65533,65532 -- chown ${n1} -1 65533
245		expect 0555,65534,65533 stat ${n0} mode,uid,gid
246		expect 0555,65534,65533 stat ${n1} mode,uid,gid
247		expect 0 chmod ${n1} 06555
248		expect 06555,65534,65533 stat ${n0} mode,uid,gid
249		expect 06555,65534,65533 stat ${n1} mode,uid,gid
250		expect 0 -u 65534 -g 65533,65532 -- chown ${n1} -1 -1
251		expect "(06555|0555),65534,65533" stat ${n0} mode,uid,gid
252		expect "(06555|0555),65534,65533" stat ${n1} mode,uid,gid
253		expect 0 unlink ${n1}
254
255		if [ "${type}" = "dir" ]; then
256			expect 0 rmdir ${n0}
257		else
258			expect 0 unlink ${n0}
259		fi
260	fi
261
262	if [ "${type}" != "symlink" ] || supported lchmod; then
263		create_file ${type} ${n0}
264
265		expect 0 lchown ${n0} 65534 65533
266		if supported lchmod; then
267			expect 0 lchmod ${n0} 06555
268		else
269			expect 0 chmod ${n0} 06555
270		fi
271		expect 06555,65534,65533 lstat ${n0} mode,uid,gid
272		expect 0 -u 65534 -g 65533,65532 lchown ${n0} 65534 65532
273		expect 0555,65534,65532 lstat ${n0} mode,uid,gid
274		if supported lchmod; then
275			expect 0 lchmod ${n0} 06555
276		else
277			expect 0 chmod ${n0} 06555
278		fi
279		expect 06555,65534,65532 lstat ${n0} mode,uid,gid
280		expect 0 -u 65534 -g 65533,65532 -- lchown ${n0} -1 65533
281		expect 0555,65534,65533 lstat ${n0} mode,uid,gid
282		if supported lchmod; then
283			expect 0 lchmod ${n0} 06555
284		else
285			expect 0 chmod ${n0} 06555
286		fi
287		expect 06555,65534,65533 lstat ${n0} mode,uid,gid
288		expect 0 -u 65534 -g 65533,65532 -- lchown ${n0} -1 -1
289		expect "(06555|0555),65534,65533" lstat ${n0} mode,uid,gid
290
291		if [ "${type}" = "dir" ]; then
292			expect 0 rmdir ${n0}
293		else
294			expect 0 unlink ${n0}
295		fi
296	fi
297done
298
299# successful chown(2) call (except uid and gid equal to -1) updates ctime.
300for type in regular dir fifo block char socket symlink; do
301	if [ "${type}" != "symlink" ]; then
302		create_file ${type} ${n0}
303
304		ctime1=`${fstest} stat ${n0} ctime`
305		sleep 1
306		expect 0 chown ${n0} 65534 65533
307		expect 65534,65533 stat ${n0} uid,gid
308		ctime2=`${fstest} stat ${n0} ctime`
309		test_check $ctime1 -lt $ctime2
310		ctime1=`${fstest} stat ${n0} ctime`
311		sleep 1
312		expect 0 -u 65534 -g 65532 chown ${n0} 65534 65532
313		expect 65534,65532 stat ${n0} uid,gid
314		ctime2=`${fstest} stat ${n0} ctime`
315		test_check $ctime1 -lt $ctime2
316
317		expect 0 symlink ${n0} ${n1}
318		ctime1=`${fstest} stat ${n1} ctime`
319		sleep 1
320		expect 0 chown ${n1} 65533 65532
321		expect 65533,65532 stat ${n1} uid,gid
322		ctime2=`${fstest} stat ${n1} ctime`
323		test_check $ctime1 -lt $ctime2
324		ctime1=`${fstest} stat ${n1} ctime`
325		sleep 1
326		expect 0 -u 65533 -g 65531 chown ${n1} 65533 65531
327		expect 65533,65531 stat ${n1} uid,gid
328		ctime2=`${fstest} stat ${n1} ctime`
329		test_check $ctime1 -lt $ctime2
330		expect 0 unlink ${n1}
331
332		if [ "${type}" = "dir" ]; then
333			expect 0 rmdir ${n0}
334		else
335			expect 0 unlink ${n0}
336		fi
337	fi
338
339	create_file ${type} ${n0}
340
341	ctime1=`${fstest} lstat ${n0} ctime`
342	sleep 1
343	expect 0 lchown ${n0} 65534 65533
344	expect 65534,65533 lstat ${n0} uid,gid
345	ctime2=`${fstest} lstat ${n0} ctime`
346	test_check $ctime1 -lt $ctime2
347	ctime1=`${fstest} lstat ${n0} ctime`
348	sleep 1
349	expect 0 -u 65534 -g 65532 lchown ${n0} 65534 65532
350	expect 65534,65532 lstat ${n0} uid,gid
351	ctime2=`${fstest} lstat ${n0} ctime`
352	test_check $ctime1 -lt $ctime2
353
354	if [ "${type}" = "dir" ]; then
355		expect 0 rmdir ${n0}
356	else
357		expect 0 unlink ${n0}
358	fi
359done
360
361for type in regular dir fifo block char socket symlink; do
362	if [ "${type}" != "symlink" ]; then
363		create_file ${type} ${n0}
364
365		ctime1=`${fstest} stat ${n0} ctime`
366		sleep 1
367		expect 0 -- chown ${n0} -1 -1
368		ctime2=`${fstest} stat ${n0} ctime`
369		todo Linux "According to POSIX: If both owner and group are -1, the times need not be updated."
370		test_check $ctime1 -eq $ctime2
371		expect 0,0 stat ${n0} uid,gid
372
373		expect 0 symlink ${n0} ${n1}
374		ctime1=`${fstest} stat ${n1} ctime`
375		sleep 1
376		expect 0 -- chown ${n1} -1 -1
377		ctime2=`${fstest} stat ${n1} ctime`
378		todo Linux "According to POSIX: If both owner and group are -1, the times need not be updated."
379		test_check $ctime1 -eq $ctime2
380		expect 0,0 stat ${n1} uid,gid
381		expect 0 unlink ${n1}
382
383		if [ "${type}" = "dir" ]; then
384			expect 0 rmdir ${n0}
385		else
386			expect 0 unlink ${n0}
387		fi
388	fi
389
390	create_file ${type} ${n0}
391
392	ctime1=`${fstest} lstat ${n0} ctime`
393	sleep 1
394	expect 0 -- lchown ${n0} -1 -1
395	ctime2=`${fstest} lstat ${n0} ctime`
396	todo Linux "According to POSIX: If both owner and group are -1, the times need not be updated."
397	test_check $ctime1 -eq $ctime2
398	expect 0,0 lstat ${n0} uid,gid
399
400	if [ "${type}" = "dir" ]; then
401		expect 0 rmdir ${n0}
402	else
403		expect 0 unlink ${n0}
404	fi
405done
406
407# unsuccessful chown(2) does not update ctime.
408for type in regular dir fifo block char socket symlink; do
409	if [ "${type}" != "symlink" ]; then
410		create_file ${type} ${n0}
411
412		ctime1=`${fstest} stat ${n0} ctime`
413		sleep 1
414		expect EPERM -u 65534 -- chown ${n0} 65534 -1
415		expect EPERM -u 65534 -g 65534 -- chown ${n0} -1 65534
416		expect EPERM -u 65534 -g 65534 chown ${n0} 65534 65534
417		ctime2=`${fstest} stat ${n0} ctime`
418		test_check $ctime1 -eq $ctime2
419		expect 0,0 stat ${n0} uid,gid
420
421		expect 0 symlink ${n0} ${n1}
422		ctime1=`${fstest} stat ${n1} ctime`
423		sleep 1
424		expect EPERM -u 65534 -- chown ${n1} 65534 -1
425		expect EPERM -u 65534 -g 65534 -- chown ${n1} -1 65534
426		expect EPERM -u 65534 -g 65534 chown ${n1} 65534 65534
427		ctime2=`${fstest} stat ${n1} ctime`
428		test_check $ctime1 -eq $ctime2
429		expect 0,0 stat ${n1} uid,gid
430		expect 0 unlink ${n1}
431
432		if [ "${type}" = "dir" ]; then
433			expect 0 rmdir ${n0}
434		else
435			expect 0 unlink ${n0}
436		fi
437	fi
438
439	create_file ${type} ${n0}
440
441	ctime1=`${fstest} lstat ${n0} ctime`
442	sleep 1
443	expect EPERM -u 65534 -- lchown ${n0} 65534 -1
444	expect EPERM -u 65534 -g 65534 -- lchown ${n0} -1 65534
445	expect EPERM -u 65534 -g 65534 lchown ${n0} 65534 65534
446	ctime2=`${fstest} lstat ${n0} ctime`
447	test_check $ctime1 -eq $ctime2
448	expect 0,0 lstat ${n0} uid,gid
449
450	if [ "${type}" = "dir" ]; then
451		expect 0 rmdir ${n0}
452	else
453		expect 0 unlink ${n0}
454	fi
455done
456
457cd ${cdir}
458expect 0 rmdir ${n2}
459