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.
26 enum fsinfo_level level;
28 union smb_fsinfo fsinfo;
30 {"DSKATTR", RAW_QFS_DSKATTR, },
31 {"ALLOCATION", RAW_QFS_ALLOCATION, },
32 {"VOLUME", RAW_QFS_VOLUME, },
33 {"VOLUME_INFO", RAW_QFS_VOLUME_INFO, },
34 {"SIZE_INFO", RAW_QFS_SIZE_INFO, },
35 {"DEVICE_INFO", RAW_QFS_DEVICE_INFO, },
36 {"ATTRIBUTE_INFO", RAW_QFS_ATTRIBUTE_INFO, },
37 {"VOLUME_INFORMATION", RAW_QFS_VOLUME_INFORMATION, },
38 {"SIZE_INFORMATION", RAW_QFS_SIZE_INFORMATION, },
39 {"DEVICE_INFORMATION", RAW_QFS_DEVICE_INFORMATION, },
40 {"ATTRIBUTE_INFORMATION", RAW_QFS_ATTRIBUTE_INFORMATION, },
41 {"QUOTA_INFORMATION", RAW_QFS_QUOTA_INFORMATION, },
42 {"FULL_SIZE_INFORMATION", RAW_QFS_FULL_SIZE_INFORMATION, },
43 {"OBJECTID_INFORMATION", RAW_QFS_OBJECTID_INFORMATION, },
49 find a level in the levels[] table
51 static union smb_fsinfo *find(const char *name)
54 for (i=0; levels[i].name; i++) {
55 if (strcmp(name, levels[i].name) == 0) {
56 return &levels[i].fsinfo;
62 /* local macros to make the code below more readable */
63 #define VAL_EQUAL(n1, v1, n2, v2) do {if (s1->n1.out.v1 != s2->n2.out.v2) { \
64 printf("%s/%s [%u] != %s/%s [%u] at %s(%d)\n", \
65 #n1, #v1, (uint_t)s1->n1.out.v1, \
66 #n2, #v2, (uint_t)s2->n2.out.v2, \
67 __FILE__, __LINE__); \
71 #define STR_EQUAL(n1, v1, n2, v2) do {if (!s1->n1.out.v1 && !s2->n2.out.v2) return True; \
72 if (!s1->n1.out.v1 || !s2->n2.out.v2) return False; \
73 if (strcmp(s1->n1.out.v1, s2->n2.out.v2)) { \
74 printf("%s/%s [%s] != %s/%s [%s] at %s(%d)\n", \
75 #n1, #v1, s1->n1.out.v1, \
76 #n2, #v2, s2->n2.out.v2, \
77 __FILE__, __LINE__); \
81 #define STRUCT_EQUAL(n1, v1, n2, v2) do {if (memcmp(&s1->n1.out.v1,&s2->n2.out.v2,sizeof(s1->n1.out.v1))) { \
82 printf("%s/%s != %s/%s at %s(%d)\n", \
85 __FILE__, __LINE__); \
89 /* used to find hints on unknown values - and to make sure
91 #define VAL_UNKNOWN(n1, v1) do {if (s1->n1.out.v1 != 0) { \
92 printf("%s/%s non-zero unknown - %u (0x%x) at %s(%d)\n", \
94 (uint_t)s1->n1.out.v1, \
95 (uint_t)s1->n1.out.v1, \
96 __FILE__, __LINE__); \
100 /* basic testing of all RAW_QFS_* calls
101 for each call we test that it succeeds, and where possible test
102 for consistency between the calls.
104 Some of the consistency tests assume that the target filesystem is
105 quiescent, which is sometimes hard to achieve
107 BOOL torture_qfsinfo(int dummy)
109 struct cli_state *cli;
113 union smb_fsinfo *s1, *s2;
116 if (!torture_open_connection(&cli)) {
120 mem_ctx = talloc_init("torture_qfsinfo");
122 /* scan all the levels, pulling the results */
123 for (i=0; levels[i].name; i++) {
124 levels[i].fsinfo.generic.level = levels[i].level;
125 levels[i].status = smb_raw_fsinfo(cli->tree, mem_ctx, &levels[i].fsinfo);
128 /* check for completely broken levels */
129 for (count=i=0; levels[i].name; i++) {
130 if (!NT_STATUS_IS_OK(levels[i].status)) {
131 printf("ERROR: level %s failed - %s\n", levels[i].name, nt_errstr(levels[i].status));
138 printf("%d levels failed\n", count);
140 printf("too many level failures - giving up\n");
145 /* check for correct aliases */
146 s1 = find("SIZE_INFO");
147 s2 = find("SIZE_INFORMATION");
149 VAL_EQUAL(size_info, total_alloc_units, size_info, total_alloc_units);
150 VAL_EQUAL(size_info, avail_alloc_units, size_info, avail_alloc_units);
151 VAL_EQUAL(size_info, sectors_per_unit, size_info, sectors_per_unit);
152 VAL_EQUAL(size_info, bytes_per_sector, size_info, bytes_per_sector);
155 s1 = find("DEVICE_INFO");
156 s2 = find("DEVICE_INFORMATION");
158 VAL_EQUAL(device_info, device_type, device_info, device_type);
159 VAL_EQUAL(device_info, characteristics, device_info, characteristics);
162 s1 = find("VOLUME_INFO");
163 s2 = find("VOLUME_INFORMATION");
165 STRUCT_EQUAL(volume_info, create_time, volume_info, create_time);
166 VAL_EQUAL (volume_info, serial_number, volume_info, serial_number);
167 STR_EQUAL (volume_info, volume_name.s, volume_info, volume_name.s);
168 printf("volume_info.volume_name = '%s'\n", s1->volume_info.out.volume_name.s);
171 s1 = find("ATTRIBUTE_INFO");
172 s2 = find("ATTRIBUTE_INFORMATION");
174 VAL_EQUAL(attribute_info, fs_attr,
175 attribute_info, fs_attr);
176 VAL_EQUAL(attribute_info, max_file_component_length,
177 attribute_info, max_file_component_length);
178 STR_EQUAL(attribute_info, fs_type.s, attribute_info, fs_type.s);
179 printf("attribute_info.fs_type = '%s'\n", s1->attribute_info.out.fs_type.s);
182 /* check for consistent disk sizes */
183 s1 = find("DSKATTR");
184 s2 = find("ALLOCATION");
187 double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size;
189 s1->dskattr.out.units_total *
190 s1->dskattr.out.blocks_per_unit *
191 s1->dskattr.out.block_size / scale;
193 s2->allocation.out.sectors_per_unit *
194 s2->allocation.out.total_alloc_units *
195 s2->allocation.out.bytes_per_sector / scale;
196 if (ABS(size1 - size2) > 1) {
197 printf("Inconsistent total size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n",
201 printf("total disk = %.0f MB\n", size1*scale/1.0e6);
204 /* and for consistent free disk space */
205 s1 = find("DSKATTR");
206 s2 = find("ALLOCATION");
209 double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size;
211 s1->dskattr.out.units_free *
212 s1->dskattr.out.blocks_per_unit *
213 s1->dskattr.out.block_size / scale;
215 s2->allocation.out.sectors_per_unit *
216 s2->allocation.out.avail_alloc_units *
217 s2->allocation.out.bytes_per_sector / scale;
218 if (ABS(size1 - size2) > 1) {
219 printf("Inconsistent avail size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n",
223 printf("free disk = %.0f MB\n", size1*scale/1.0e6);
226 /* volume info consistency */
228 s2 = find("VOLUME_INFO");
230 VAL_EQUAL(volume, serial_number, volume_info, serial_number);
231 STR_EQUAL(volume, volume_name.s, volume_info, volume_name.s);
234 /* disk size consistency - notice that 'avail_alloc_units' maps to the caller
235 available allocation units, not the total */
236 s1 = find("SIZE_INFO");
237 s2 = find("FULL_SIZE_INFORMATION");
239 VAL_EQUAL(size_info, total_alloc_units, full_size_information, total_alloc_units);
240 VAL_EQUAL(size_info, avail_alloc_units, full_size_information, call_avail_alloc_units);
241 VAL_EQUAL(size_info, sectors_per_unit, full_size_information, sectors_per_unit);
242 VAL_EQUAL(size_info, bytes_per_sector, full_size_information, bytes_per_sector);
245 /* check for non-zero unknown fields - if we find them
246 they might give us some hints */
247 s1 = find("QUOTA_INFORMATION");
249 VAL_UNKNOWN(quota_information, unknown[0]);
250 VAL_UNKNOWN(quota_information, unknown[1]);
251 VAL_UNKNOWN(quota_information, unknown[2]);
254 s1 = find("OBJECTID_INFORMATION");
256 VAL_UNKNOWN(objectid_information, unknown[0]);
257 VAL_UNKNOWN(objectid_information, unknown[1]);
258 VAL_UNKNOWN(objectid_information, unknown[2]);
259 VAL_UNKNOWN(objectid_information, unknown[3]);
260 VAL_UNKNOWN(objectid_information, unknown[4]);
261 VAL_UNKNOWN(objectid_information, unknown[5]);
265 #define STR_CHECK(sname, stype, field, flags) do { \
268 if (wire_bad_flags(&s1->stype.out.field, flags)) { \
269 printf("(%d) incorrect string termination in %s/%s\n", \
270 __LINE__, #stype, #field); \
275 /* check for correct termination */
276 STR_CHECK("VOLUME", volume, volume_name, 0);
277 STR_CHECK("VOLUME_INFO", volume_info, volume_name, STR_UNICODE);
278 STR_CHECK("VOLUME_INFORMATION", volume_info, volume_name, STR_UNICODE);
279 STR_CHECK("ATTRIBUTE_INFO", attribute_info, fs_type, STR_UNICODE);
280 STR_CHECK("ATTRIBUTE_INFORMATION", attribute_info, fs_type, STR_UNICODE);
283 torture_close_connection(cli);
284 talloc_destroy(mem_ctx);