1 #include "defs.h"
2 #ifdef HAVE_SYS_VFS_H
3 # include <sys/vfs.h>
4 #endif
5 #include "xlat/fsmagic.h"
6 
7 static const char *
sprintfstype(const unsigned int magic)8 sprintfstype(const unsigned int magic)
9 {
10 	static char buf[32];
11 	const char *s;
12 
13 	s = xlat_search(fsmagic, ARRAY_SIZE(fsmagic), magic);
14 	if (s) {
15 		sprintf(buf, "\"%s\"", s);
16 		return buf;
17 	}
18 	sprintf(buf, "%#x", magic);
19 	return buf;
20 }
21 
22 static void
printstatfs(struct tcb * tcp,const long addr)23 printstatfs(struct tcb *tcp, const long addr)
24 {
25 	struct statfs statbuf;
26 
27 	if (syserror(tcp) || !verbose(tcp)) {
28 		tprintf("%#lx", addr);
29 		return;
30 	}
31 	if (umove(tcp, addr, &statbuf) < 0) {
32 		tprints("{...}");
33 		return;
34 	}
35 	tprintf("{f_type=%s, f_bsize=%lu, f_blocks=%lu, f_bfree=%lu, ",
36 		sprintfstype(statbuf.f_type),
37 		(unsigned long)statbuf.f_bsize,
38 		(unsigned long)statbuf.f_blocks,
39 		(unsigned long)statbuf.f_bfree);
40 	tprintf("f_bavail=%lu, f_files=%lu, f_ffree=%lu, f_fsid={%d, %d}",
41 		(unsigned long)statbuf.f_bavail,
42 		(unsigned long)statbuf.f_files,
43 		(unsigned long)statbuf.f_ffree,
44 		statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1]);
45 	tprintf(", f_namelen=%lu", (unsigned long)statbuf.f_namelen);
46 #ifdef _STATFS_F_FRSIZE
47 	tprintf(", f_frsize=%lu", (unsigned long)statbuf.f_frsize);
48 #endif
49 #ifdef _STATFS_F_FLAGS
50 	tprintf(", f_flags=%lu", (unsigned long)statbuf.f_flags);
51 #endif
52 	tprints("}");
53 }
54 
SYS_FUNC(statfs)55 SYS_FUNC(statfs)
56 {
57 	if (entering(tcp)) {
58 		printpath(tcp, tcp->u_arg[0]);
59 		tprints(", ");
60 	} else {
61 		printstatfs(tcp, tcp->u_arg[1]);
62 	}
63 	return 0;
64 }
65 
SYS_FUNC(fstatfs)66 SYS_FUNC(fstatfs)
67 {
68 	if (entering(tcp)) {
69 		printfd(tcp, tcp->u_arg[0]);
70 		tprints(", ");
71 	} else {
72 		printstatfs(tcp, tcp->u_arg[1]);
73 	}
74 	return 0;
75 }
76 
77 #ifdef HAVE_STRUCT_STATFS64
78 static void
printstatfs64(struct tcb * tcp,long addr)79 printstatfs64(struct tcb *tcp, long addr)
80 {
81 	struct statfs64 statbuf;
82 
83 	if (syserror(tcp) || !verbose(tcp)) {
84 		tprintf("%#lx", addr);
85 		return;
86 	}
87 	if (umove(tcp, addr, &statbuf) < 0) {
88 		tprints("{...}");
89 		return;
90 	}
91 	tprintf("{f_type=%s, f_bsize=%llu, f_blocks=%llu, f_bfree=%llu, ",
92 		sprintfstype(statbuf.f_type),
93 		(unsigned long long)statbuf.f_bsize,
94 		(unsigned long long)statbuf.f_blocks,
95 		(unsigned long long)statbuf.f_bfree);
96 	tprintf("f_bavail=%llu, f_files=%llu, f_ffree=%llu, f_fsid={%d, %d}",
97 		(unsigned long long)statbuf.f_bavail,
98 		(unsigned long long)statbuf.f_files,
99 		(unsigned long long)statbuf.f_ffree,
100 		statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1]);
101 	tprintf(", f_namelen=%lu", (unsigned long)statbuf.f_namelen);
102 #ifdef _STATFS_F_FRSIZE
103 	tprintf(", f_frsize=%llu", (unsigned long long)statbuf.f_frsize);
104 #endif
105 #ifdef _STATFS_F_FLAGS
106 	tprintf(", f_flags=%llu", (unsigned long long)statbuf.f_flags);
107 #endif
108 	tprints("}");
109 }
110 
111 struct compat_statfs64 {
112 	uint32_t f_type;
113 	uint32_t f_bsize;
114 	uint64_t f_blocks;
115 	uint64_t f_bfree;
116 	uint64_t f_bavail;
117 	uint64_t f_files;
118 	uint64_t f_ffree;
119 	fsid_t f_fsid;
120 	uint32_t f_namelen;
121 	uint32_t f_frsize;
122 	uint32_t f_flags;
123 	uint32_t f_spare[4];
124 }
125 #if defined AARCH64 || defined X86_64 || defined X32 || defined IA64
126   ATTRIBUTE_PACKED ATTRIBUTE_ALIGNED(4)
127 #endif
128 ;
129 #if defined AARCH64 || defined ARM
130 /* See arch/arm/kernel/sys_oabi-compat.c for details. */
131 # define COMPAT_STATFS64_PADDED_SIZE (sizeof(struct compat_statfs64) + 4)
132 #endif
133 
134 static void
printcompat_statfs64(struct tcb * tcp,const long addr)135 printcompat_statfs64(struct tcb *tcp, const long addr)
136 {
137 	struct compat_statfs64 statbuf;
138 
139 	if (syserror(tcp) || !verbose(tcp)) {
140 		tprintf("%#lx", addr);
141 		return;
142 	}
143 	if (umove(tcp, addr, &statbuf) < 0) {
144 		tprints("{...}");
145 		return;
146 	}
147 	tprintf("{f_type=%s, f_bsize=%lu, f_blocks=%llu, f_bfree=%llu, ",
148 		sprintfstype(statbuf.f_type),
149 		(unsigned long)statbuf.f_bsize,
150 		(unsigned long long)statbuf.f_blocks,
151 		(unsigned long long)statbuf.f_bfree);
152 	tprintf("f_bavail=%llu, f_files=%llu, f_ffree=%llu, f_fsid={%d, %d}",
153 		(unsigned long long)statbuf.f_bavail,
154 		(unsigned long long)statbuf.f_files,
155 		(unsigned long long)statbuf.f_ffree,
156 		statbuf.f_fsid.__val[0], statbuf.f_fsid.__val[1]);
157 	tprintf(", f_namelen=%lu", (unsigned long)statbuf.f_namelen);
158 	tprintf(", f_frsize=%lu", (unsigned long)statbuf.f_frsize);
159 	tprintf(", f_flags=%lu}", (unsigned long)statbuf.f_frsize);
160 }
161 
162 static int
do_statfs64_fstatfs64(struct tcb * tcp)163 do_statfs64_fstatfs64(struct tcb *tcp)
164 {
165 	if (entering(tcp)) {
166 		tprintf(", %lu, ", tcp->u_arg[1]);
167 	} else {
168 		if (tcp->u_arg[1] == sizeof(struct statfs64))
169 			printstatfs64(tcp, tcp->u_arg[2]);
170 		else if (tcp->u_arg[1] == sizeof(struct compat_statfs64)
171 #ifdef COMPAT_STATFS64_PADDED_SIZE
172 			 || tcp->u_arg[1] == COMPAT_STATFS64_PADDED_SIZE
173 #endif
174 									)
175 			printcompat_statfs64(tcp, tcp->u_arg[2]);
176 		else
177 			tprints("{???}");
178 	}
179 	return 0;
180 }
181 
SYS_FUNC(statfs64)182 SYS_FUNC(statfs64)
183 {
184 	if (entering(tcp))
185 		printpath(tcp, tcp->u_arg[0]);
186 	return do_statfs64_fstatfs64(tcp);
187 }
188 
SYS_FUNC(fstatfs64)189 SYS_FUNC(fstatfs64)
190 {
191 	if (entering(tcp))
192 		printfd(tcp, tcp->u_arg[0]);
193 	return do_statfs64_fstatfs64(tcp);
194 }
195 #endif /* HAVE_STRUCT_STATFS64 */
196 
197 #ifdef ALPHA
SYS_FUNC(osf_statfs)198 SYS_FUNC(osf_statfs)
199 {
200 	if (entering(tcp)) {
201 		printpath(tcp, tcp->u_arg[0]);
202 		tprints(", ");
203 	} else {
204 		printstatfs(tcp, tcp->u_arg[1]);
205 		tprintf(", %lu", tcp->u_arg[2]);
206 	}
207 	return 0;
208 }
209 
SYS_FUNC(osf_fstatfs)210 SYS_FUNC(osf_fstatfs)
211 {
212 	if (entering(tcp)) {
213 		tprintf("%lu, ", tcp->u_arg[0]);
214 	} else {
215 		printstatfs(tcp, tcp->u_arg[1]);
216 		tprintf(", %lu", tcp->u_arg[2]);
217 	}
218 	return 0;
219 }
220 #endif /* ALPHA */
221