1 /*
2  * Copyright (c) 2002-2005 Roland McGrath <roland@redhat.com>
3  * Copyright (c) 2004 Ulrich Drepper <drepper@redhat.com>
4  * Copyright (c) 2005-2015 Dmitry V. Levin <ldv@altlinux.org>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  * 3. The name of the author may not be used to endorse or promote products
16  *    derived from this software without specific prior written permission.
17  *
18  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
19  * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
20  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
21  * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
22  * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
23  * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
24  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
25  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
26  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
27  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
28  */
29 
30 #include "defs.h"
31 
32 #ifdef HAVE_SYS_XATTR_H
33 # include <sys/xattr.h>
34 #endif
35 
36 #include "xlat/xattrflags.h"
37 
38 static void
print_xattr_val(struct tcb * tcp,unsigned long addr,unsigned long insize,unsigned long size)39 print_xattr_val(struct tcb *tcp,
40 		unsigned long addr,
41 		unsigned long insize,
42 		unsigned long size)
43 {
44 	char *buf = NULL;
45 	unsigned int len;
46 
47 	tprints(", ");
48 
49 	if (insize == 0)
50 		goto done;
51 
52 	len = size;
53 	if (size != (unsigned long) len)
54 		goto done;
55 
56 	if (!len) {
57 		tprintf("\"\", %ld", insize);
58 		return;
59 	}
60 
61 	if (!verbose(tcp) || (exiting(tcp) && syserror(tcp)))
62 		goto done;
63 
64 	buf = malloc(len);
65 	if (!buf)
66 		goto done;
67 
68 	if (umoven(tcp, addr, len, buf) < 0) {
69 		free(buf);
70 		buf = NULL;
71 		goto done;
72 	}
73 
74 	/* Don't print terminating NUL if there is one. */
75 	if (buf[len - 1] == '\0')
76 		--len;
77 
78 done:
79 	if (buf) {
80 		print_quoted_string(buf, len, 0);
81 		free(buf);
82 	} else {
83 		printaddr(addr);
84 	}
85 	tprintf(", %ld", insize);
86 }
87 
SYS_FUNC(setxattr)88 SYS_FUNC(setxattr)
89 {
90 	printpath(tcp, tcp->u_arg[0]);
91 	tprints(", ");
92 	printstr(tcp, tcp->u_arg[1], -1);
93 	print_xattr_val(tcp, tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[3]);
94 	tprints(", ");
95 	printflags(xattrflags, tcp->u_arg[4], "XATTR_???");
96 	return RVAL_DECODED;
97 }
98 
SYS_FUNC(fsetxattr)99 SYS_FUNC(fsetxattr)
100 {
101 	printfd(tcp, tcp->u_arg[0]);
102 	tprints(", ");
103 	printstr(tcp, tcp->u_arg[1], -1);
104 	print_xattr_val(tcp, tcp->u_arg[2], tcp->u_arg[3], tcp->u_arg[3]);
105 	tprints(", ");
106 	printflags(xattrflags, tcp->u_arg[4], "XATTR_???");
107 	return RVAL_DECODED;
108 }
109 
SYS_FUNC(getxattr)110 SYS_FUNC(getxattr)
111 {
112 	if (entering(tcp)) {
113 		printpath(tcp, tcp->u_arg[0]);
114 		tprints(", ");
115 		printstr(tcp, tcp->u_arg[1], -1);
116 	} else {
117 		print_xattr_val(tcp, tcp->u_arg[2], tcp->u_arg[3], tcp->u_rval);
118 	}
119 	return 0;
120 }
121 
SYS_FUNC(fgetxattr)122 SYS_FUNC(fgetxattr)
123 {
124 	if (entering(tcp)) {
125 		printfd(tcp, tcp->u_arg[0]);
126 		tprints(", ");
127 		printstr(tcp, tcp->u_arg[1], -1);
128 	} else {
129 		print_xattr_val(tcp, tcp->u_arg[2], tcp->u_arg[3], tcp->u_rval);
130 	}
131 	return 0;
132 }
133 
134 static void
print_xattr_list(struct tcb * tcp,unsigned long addr,unsigned long size)135 print_xattr_list(struct tcb *tcp, unsigned long addr, unsigned long size)
136 {
137 	if (syserror(tcp)) {
138 		printaddr(addr);
139 	} else {
140 		unsigned long len =
141 			(size < (unsigned long) tcp->u_rval) ?
142 				size : (unsigned long) tcp->u_rval;
143 		printstr(tcp, addr, len);
144 	}
145 	tprintf(", %lu", size);
146 }
147 
SYS_FUNC(listxattr)148 SYS_FUNC(listxattr)
149 {
150 	if (entering(tcp)) {
151 		printpath(tcp, tcp->u_arg[0]);
152 		tprints(", ");
153 	} else {
154 		print_xattr_list(tcp, tcp->u_arg[1], tcp->u_arg[2]);
155 	}
156 	return 0;
157 }
158 
SYS_FUNC(flistxattr)159 SYS_FUNC(flistxattr)
160 {
161 	if (entering(tcp)) {
162 		printfd(tcp, tcp->u_arg[0]);
163 		tprints(", ");
164 	} else {
165 		print_xattr_list(tcp, tcp->u_arg[1], tcp->u_arg[2]);
166 	}
167 	return 0;
168 }
169 
SYS_FUNC(removexattr)170 SYS_FUNC(removexattr)
171 {
172 	printpath(tcp, tcp->u_arg[0]);
173 	tprints(", ");
174 	printstr(tcp, tcp->u_arg[1], -1);
175 	return RVAL_DECODED;
176 }
177 
SYS_FUNC(fremovexattr)178 SYS_FUNC(fremovexattr)
179 {
180 	printfd(tcp, tcp->u_arg[0]);
181 	tprints(", ");
182 	printstr(tcp, tcp->u_arg[1], -1);
183 	return RVAL_DECODED;
184 }
185