2 Unix SMB/CIFS implementation.
3 RAW_QFS_* individual test suite
4 Copyright (C) Andrew Tridgell 2003
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include "libcli/raw/libcliraw.h"
27 enum smb_fsinfo_level level;
28 uint32_t capability_mask;
30 union smb_fsinfo fsinfo;
32 {"DSKATTR", RAW_QFS_DSKATTR, },
33 {"ALLOCATION", RAW_QFS_ALLOCATION, },
34 {"VOLUME", RAW_QFS_VOLUME, },
35 {"VOLUME_INFO", RAW_QFS_VOLUME_INFO, },
36 {"SIZE_INFO", RAW_QFS_SIZE_INFO, },
37 {"DEVICE_INFO", RAW_QFS_DEVICE_INFO, },
38 {"ATTRIBUTE_INFO", RAW_QFS_ATTRIBUTE_INFO, },
39 {"UNIX_INFO", RAW_QFS_UNIX_INFO, CAP_UNIX},
40 {"VOLUME_INFORMATION", RAW_QFS_VOLUME_INFORMATION, },
41 {"SIZE_INFORMATION", RAW_QFS_SIZE_INFORMATION, },
42 {"DEVICE_INFORMATION", RAW_QFS_DEVICE_INFORMATION, },
43 {"ATTRIBUTE_INFORMATION", RAW_QFS_ATTRIBUTE_INFORMATION, },
44 {"QUOTA_INFORMATION", RAW_QFS_QUOTA_INFORMATION, },
45 {"FULL_SIZE_INFORMATION", RAW_QFS_FULL_SIZE_INFORMATION, },
46 {"OBJECTID_INFORMATION", RAW_QFS_OBJECTID_INFORMATION, },
52 find a level in the levels[] table
54 static union smb_fsinfo *find(const char *name)
57 for (i=0; levels[i].name; i++) {
58 if (strcmp(name, levels[i].name) == 0 &&
59 NT_STATUS_IS_OK(levels[i].status)) {
60 return &levels[i].fsinfo;
66 /* local macros to make the code below more readable */
67 #define VAL_EQUAL(n1, v1, n2, v2) do {if (s1->n1.out.v1 != s2->n2.out.v2) { \
68 printf("%s/%s [%u] != %s/%s [%u] at %s(%d)\n", \
69 #n1, #v1, (uint_t)s1->n1.out.v1, \
70 #n2, #v2, (uint_t)s2->n2.out.v2, \
71 __FILE__, __LINE__); \
75 #define STR_EQUAL(n1, v1, n2, v2) do {if (!s1->n1.out.v1 && !s2->n2.out.v2) return True; \
76 if (!s1->n1.out.v1 || !s2->n2.out.v2) return False; \
77 if (strcmp(s1->n1.out.v1, s2->n2.out.v2)) { \
78 printf("%s/%s [%s] != %s/%s [%s] at %s(%d)\n", \
79 #n1, #v1, s1->n1.out.v1, \
80 #n2, #v2, s2->n2.out.v2, \
81 __FILE__, __LINE__); \
85 #define STRUCT_EQUAL(n1, v1, n2, v2) do {if (memcmp(&s1->n1.out.v1,&s2->n2.out.v2,sizeof(s1->n1.out.v1))) { \
86 printf("%s/%s != %s/%s at %s(%d)\n", \
89 __FILE__, __LINE__); \
93 /* used to find hints on unknown values - and to make sure
95 #define VAL_UNKNOWN(n1, v1) do {if (s1->n1.out.v1 != 0) { \
96 printf("%s/%s non-zero unknown - %u (0x%x) at %s(%d)\n", \
98 (uint_t)s1->n1.out.v1, \
99 (uint_t)s1->n1.out.v1, \
100 __FILE__, __LINE__); \
104 /* basic testing of all RAW_QFS_* calls
105 for each call we test that it succeeds, and where possible test
106 for consistency between the calls.
108 Some of the consistency tests assume that the target filesystem is
109 quiescent, which is sometimes hard to achieve
111 BOOL torture_raw_qfsinfo(void)
113 struct smbcli_state *cli;
117 union smb_fsinfo *s1, *s2;
120 if (!torture_open_connection(&cli)) {
124 mem_ctx = talloc_init("torture_qfsinfo");
126 /* scan all the levels, pulling the results */
127 for (i=0; levels[i].name; i++) {
128 printf("Running level %s\n", levels[i].name);
129 levels[i].fsinfo.generic.level = levels[i].level;
130 levels[i].status = smb_raw_fsinfo(cli->tree, mem_ctx, &levels[i].fsinfo);
133 /* check for completely broken levels */
134 for (count=i=0; levels[i].name; i++) {
135 uint32_t cap = cli->transport->negotiate.capabilities;
136 /* see if this server claims to support this level */
137 if ((cap & levels[i].capability_mask) != levels[i].capability_mask) {
141 if (!NT_STATUS_IS_OK(levels[i].status)) {
142 printf("ERROR: level %s failed - %s\n",
143 levels[i].name, nt_errstr(levels[i].status));
150 printf("%d levels failed\n", count);
152 printf("too many level failures - giving up\n");
157 printf("check for correct aliases\n");
158 s1 = find("SIZE_INFO");
159 s2 = find("SIZE_INFORMATION");
161 VAL_EQUAL(size_info, total_alloc_units, size_info, total_alloc_units);
162 VAL_EQUAL(size_info, avail_alloc_units, size_info, avail_alloc_units);
163 VAL_EQUAL(size_info, sectors_per_unit, size_info, sectors_per_unit);
164 VAL_EQUAL(size_info, bytes_per_sector, size_info, bytes_per_sector);
167 s1 = find("DEVICE_INFO");
168 s2 = find("DEVICE_INFORMATION");
170 VAL_EQUAL(device_info, device_type, device_info, device_type);
171 VAL_EQUAL(device_info, characteristics, device_info, characteristics);
174 s1 = find("VOLUME_INFO");
175 s2 = find("VOLUME_INFORMATION");
177 STRUCT_EQUAL(volume_info, create_time, volume_info, create_time);
178 VAL_EQUAL (volume_info, serial_number, volume_info, serial_number);
179 STR_EQUAL (volume_info, volume_name.s, volume_info, volume_name.s);
180 printf("volume_info.volume_name = '%s'\n", s1->volume_info.out.volume_name.s);
183 s1 = find("ATTRIBUTE_INFO");
184 s2 = find("ATTRIBUTE_INFORMATION");
186 VAL_EQUAL(attribute_info, fs_attr,
187 attribute_info, fs_attr);
188 VAL_EQUAL(attribute_info, max_file_component_length,
189 attribute_info, max_file_component_length);
190 STR_EQUAL(attribute_info, fs_type.s, attribute_info, fs_type.s);
191 printf("attribute_info.fs_type = '%s'\n", s1->attribute_info.out.fs_type.s);
194 printf("check for consistent disk sizes\n");
195 s1 = find("DSKATTR");
196 s2 = find("ALLOCATION");
199 double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size;
201 s1->dskattr.out.units_total *
202 s1->dskattr.out.blocks_per_unit *
203 s1->dskattr.out.block_size / scale;
205 s2->allocation.out.sectors_per_unit *
206 s2->allocation.out.total_alloc_units *
207 s2->allocation.out.bytes_per_sector / scale;
208 if (ABS(size1 - size2) > 1) {
209 printf("Inconsistent total size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n",
213 printf("total disk = %.0f MB\n", size1*scale/1.0e6);
216 printf("check consistent free disk space\n");
217 s1 = find("DSKATTR");
218 s2 = find("ALLOCATION");
221 double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size;
223 s1->dskattr.out.units_free *
224 s1->dskattr.out.blocks_per_unit *
225 s1->dskattr.out.block_size / scale;
227 s2->allocation.out.sectors_per_unit *
228 s2->allocation.out.avail_alloc_units *
229 s2->allocation.out.bytes_per_sector / scale;
230 if (ABS(size1 - size2) > 1) {
231 printf("Inconsistent avail size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n",
235 printf("free disk = %.0f MB\n", size1*scale/1.0e6);
238 printf("volume info consistency\n");
240 s2 = find("VOLUME_INFO");
242 VAL_EQUAL(volume, serial_number, volume_info, serial_number);
243 STR_EQUAL(volume, volume_name.s, volume_info, volume_name.s);
246 /* disk size consistency - notice that 'avail_alloc_units' maps to the caller
247 available allocation units, not the total */
248 s1 = find("SIZE_INFO");
249 s2 = find("FULL_SIZE_INFORMATION");
251 VAL_EQUAL(size_info, total_alloc_units, full_size_information, total_alloc_units);
252 VAL_EQUAL(size_info, avail_alloc_units, full_size_information, call_avail_alloc_units);
253 VAL_EQUAL(size_info, sectors_per_unit, full_size_information, sectors_per_unit);
254 VAL_EQUAL(size_info, bytes_per_sector, full_size_information, bytes_per_sector);
257 printf("check for non-zero unknown fields\n");
258 s1 = find("QUOTA_INFORMATION");
260 VAL_UNKNOWN(quota_information, unknown[0]);
261 VAL_UNKNOWN(quota_information, unknown[1]);
262 VAL_UNKNOWN(quota_information, unknown[2]);
265 s1 = find("OBJECTID_INFORMATION");
267 VAL_UNKNOWN(objectid_information, unknown[0]);
268 VAL_UNKNOWN(objectid_information, unknown[1]);
269 VAL_UNKNOWN(objectid_information, unknown[2]);
270 VAL_UNKNOWN(objectid_information, unknown[3]);
271 VAL_UNKNOWN(objectid_information, unknown[4]);
272 VAL_UNKNOWN(objectid_information, unknown[5]);
276 #define STR_CHECK(sname, stype, field, flags) do { \
279 if (wire_bad_flags(&s1->stype.out.field, flags, cli)) { \
280 printf("(%d) incorrect string termination in %s/%s\n", \
281 __LINE__, #stype, #field); \
286 printf("check for correct termination\n");
287 STR_CHECK("VOLUME", volume, volume_name, 0);
288 STR_CHECK("VOLUME_INFO", volume_info, volume_name, STR_UNICODE);
289 STR_CHECK("VOLUME_INFORMATION", volume_info, volume_name, STR_UNICODE);
290 STR_CHECK("ATTRIBUTE_INFO", attribute_info, fs_type, STR_UNICODE);
291 STR_CHECK("ATTRIBUTE_INFORMATION", attribute_info, fs_type, STR_UNICODE);
294 torture_close_connection(cli);
295 talloc_destroy(mem_ctx);