libsmbconf: Document smbconf_get_config().
[Samba.git] / source4 / torture / raw / qfsinfo.c
blob111eac14d5cf28140416036de56a667d0f414695
1 /*
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 3 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, see <http://www.gnu.org/licenses/>.
20 #include "includes.h"
21 #include "libcli/libcli.h"
22 #include "torture/util.h"
25 static struct {
26 const char *name;
27 enum smb_fsinfo_level level;
28 uint32_t capability_mask;
29 NTSTATUS status;
30 union smb_fsinfo fsinfo;
31 } levels[] = {
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 #if 0
47 /* w2k3 seems to no longer support this */
48 {"OBJECTID_INFORMATION", RAW_QFS_OBJECTID_INFORMATION, },
49 #endif
50 { NULL, }
55 find a level in the levels[] table
57 static union smb_fsinfo *find(const char *name)
59 int i;
60 for (i=0; levels[i].name; i++) {
61 if (strcmp(name, levels[i].name) == 0 &&
62 NT_STATUS_IS_OK(levels[i].status)) {
63 return &levels[i].fsinfo;
66 return NULL;
69 /* local macros to make the code below more readable */
70 #define VAL_EQUAL(n1, v1, n2, v2) do {if (s1->n1.out.v1 != s2->n2.out.v2) { \
71 printf("%s/%s [%u] != %s/%s [%u] at %s(%d)\n", \
72 #n1, #v1, (unsigned int)s1->n1.out.v1, \
73 #n2, #v2, (unsigned int)s2->n2.out.v2, \
74 __FILE__, __LINE__); \
75 ret = false; \
76 }} while(0)
78 #define VAL_APPROX_EQUAL(n1, v1, n2, v2) do {if (abs((int)(s1->n1.out.v1) - (int)(s2->n2.out.v2)) > 0.1*s1->n1.out.v1) { \
79 printf("%s/%s [%u] != %s/%s [%u] at %s(%d)\n", \
80 #n1, #v1, (unsigned int)s1->n1.out.v1, \
81 #n2, #v2, (unsigned int)s2->n2.out.v2, \
82 __FILE__, __LINE__); \
83 ret = false; \
84 }} while(0)
86 #define STR_EQUAL(n1, v1, n2, v2) do { \
87 if (strcmp_safe(s1->n1.out.v1, s2->n2.out.v2)) { \
88 printf("%s/%s [%s] != %s/%s [%s] at %s(%d)\n", \
89 #n1, #v1, s1->n1.out.v1, \
90 #n2, #v2, s2->n2.out.v2, \
91 __FILE__, __LINE__); \
92 ret = false; \
93 }} while(0)
95 #define STRUCT_EQUAL(n1, v1, n2, v2) do {if (memcmp(&s1->n1.out.v1,&s2->n2.out.v2,sizeof(s1->n1.out.v1))) { \
96 printf("%s/%s != %s/%s at %s(%d)\n", \
97 #n1, #v1, \
98 #n2, #v2, \
99 __FILE__, __LINE__); \
100 ret = false; \
101 }} while(0)
103 /* used to find hints on unknown values - and to make sure
104 we zero-fill */
105 #define VAL_UNKNOWN(n1, v1) do {if (s1->n1.out.v1 != 0) { \
106 printf("%s/%s non-zero unknown - %u (0x%x) at %s(%d)\n", \
107 #n1, #v1, \
108 (unsigned int)s1->n1.out.v1, \
109 (unsigned int)s1->n1.out.v1, \
110 __FILE__, __LINE__); \
111 ret = false; \
112 }} while(0)
114 /* basic testing of all RAW_QFS_* calls
115 for each call we test that it succeeds, and where possible test
116 for consistency between the calls.
118 Some of the consistency tests assume that the target filesystem is
119 quiescent, which is sometimes hard to achieve
121 bool torture_raw_qfsinfo(struct torture_context *torture,
122 struct smbcli_state *cli)
124 int i;
125 bool ret = true;
126 int count;
127 union smb_fsinfo *s1, *s2;
129 /* scan all the levels, pulling the results */
130 for (i=0; levels[i].name; i++) {
131 torture_comment(torture, "Running level %s\n", levels[i].name);
132 levels[i].fsinfo.generic.level = levels[i].level;
133 levels[i].status = smb_raw_fsinfo(cli->tree, torture, &levels[i].fsinfo);
136 /* check for completely broken levels */
137 for (count=i=0; levels[i].name; i++) {
138 uint32_t cap = cli->transport->negotiate.capabilities;
139 /* see if this server claims to support this level */
140 if ((cap & levels[i].capability_mask) != levels[i].capability_mask) {
141 continue;
144 if (!NT_STATUS_IS_OK(levels[i].status)) {
145 printf("ERROR: level %s failed - %s\n",
146 levels[i].name, nt_errstr(levels[i].status));
147 count++;
151 if (count != 0) {
152 torture_comment(torture, "%d levels failed\n", count);
153 torture_assert(torture, count > 13, "too many level failures - giving up");
156 torture_comment(torture, "check for correct aliases\n");
157 s1 = find("SIZE_INFO");
158 s2 = find("SIZE_INFORMATION");
159 if (s1 && s2) {
160 VAL_EQUAL(size_info, total_alloc_units, size_info, total_alloc_units);
161 VAL_APPROX_EQUAL(size_info, avail_alloc_units, size_info, avail_alloc_units);
162 VAL_EQUAL(size_info, sectors_per_unit, size_info, sectors_per_unit);
163 VAL_EQUAL(size_info, bytes_per_sector, size_info, bytes_per_sector);
166 s1 = find("DEVICE_INFO");
167 s2 = find("DEVICE_INFORMATION");
168 if (s1 && s2) {
169 VAL_EQUAL(device_info, device_type, device_info, device_type);
170 VAL_EQUAL(device_info, characteristics, device_info, characteristics);
173 s1 = find("VOLUME_INFO");
174 s2 = find("VOLUME_INFORMATION");
175 if (s1 && s2) {
176 STRUCT_EQUAL(volume_info, create_time, volume_info, create_time);
177 VAL_EQUAL (volume_info, serial_number, volume_info, serial_number);
178 STR_EQUAL (volume_info, volume_name.s, volume_info, volume_name.s);
179 torture_comment(torture, "volume_info.volume_name = '%s'\n", s1->volume_info.out.volume_name.s);
182 s1 = find("ATTRIBUTE_INFO");
183 s2 = find("ATTRIBUTE_INFORMATION");
184 if (s1 && s2) {
185 VAL_EQUAL(attribute_info, fs_attr,
186 attribute_info, fs_attr);
187 VAL_EQUAL(attribute_info, max_file_component_length,
188 attribute_info, max_file_component_length);
189 STR_EQUAL(attribute_info, fs_type.s, attribute_info, fs_type.s);
190 torture_comment(torture, "attribute_info.fs_type = '%s'\n", s1->attribute_info.out.fs_type.s);
193 torture_comment(torture, "check for consistent disk sizes\n");
194 s1 = find("DSKATTR");
195 s2 = find("ALLOCATION");
196 if (s1 && s2) {
197 double size1, size2;
198 double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size;
199 size1 = 1.0 *
200 s1->dskattr.out.units_total *
201 s1->dskattr.out.blocks_per_unit *
202 s1->dskattr.out.block_size / scale;
203 size2 = 1.0 *
204 s2->allocation.out.sectors_per_unit *
205 s2->allocation.out.total_alloc_units *
206 s2->allocation.out.bytes_per_sector / scale;
207 if (abs(size1 - size2) > 1) {
208 printf("Inconsistent total size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n",
209 size1, size2);
210 ret = false;
212 torture_comment(torture, "total disk = %.0f MB\n", size1*scale/1.0e6);
215 torture_comment(torture, "check consistent free disk space\n");
216 s1 = find("DSKATTR");
217 s2 = find("ALLOCATION");
218 if (s1 && s2) {
219 double size1, size2;
220 double scale = s1->dskattr.out.blocks_per_unit * s1->dskattr.out.block_size;
221 size1 = 1.0 *
222 s1->dskattr.out.units_free *
223 s1->dskattr.out.blocks_per_unit *
224 s1->dskattr.out.block_size / scale;
225 size2 = 1.0 *
226 s2->allocation.out.sectors_per_unit *
227 s2->allocation.out.avail_alloc_units *
228 s2->allocation.out.bytes_per_sector / scale;
229 if (abs(size1 - size2) > 1) {
230 printf("Inconsistent avail size in DSKATTR and ALLOCATION - size1=%.0f size2=%.0f\n",
231 size1, size2);
232 ret = false;
234 torture_comment(torture, "free disk = %.0f MB\n", size1*scale/1.0e6);
237 torture_comment(torture, "volume info consistency\n");
238 s1 = find("VOLUME");
239 s2 = find("VOLUME_INFO");
240 if (s1 && s2) {
241 VAL_EQUAL(volume, serial_number, volume_info, serial_number);
242 STR_EQUAL(volume, volume_name.s, volume_info, volume_name.s);
245 /* disk size consistency - notice that 'avail_alloc_units' maps to the caller
246 available allocation units, not the total */
247 s1 = find("SIZE_INFO");
248 s2 = find("FULL_SIZE_INFORMATION");
249 if (s1 && s2) {
250 VAL_EQUAL(size_info, total_alloc_units, full_size_information, total_alloc_units);
251 VAL_APPROX_EQUAL(size_info, avail_alloc_units, full_size_information, call_avail_alloc_units);
252 VAL_EQUAL(size_info, sectors_per_unit, full_size_information, sectors_per_unit);
253 VAL_EQUAL(size_info, bytes_per_sector, full_size_information, bytes_per_sector);
256 printf("check for non-zero unknown fields\n");
257 s1 = find("QUOTA_INFORMATION");
258 if (s1) {
259 VAL_UNKNOWN(quota_information, unknown[0]);
260 VAL_UNKNOWN(quota_information, unknown[1]);
261 VAL_UNKNOWN(quota_information, unknown[2]);
264 s1 = find("OBJECTID_INFORMATION");
265 if (s1) {
266 VAL_UNKNOWN(objectid_information, unknown[0]);
267 VAL_UNKNOWN(objectid_information, unknown[1]);
268 VAL_UNKNOWN(objectid_information, unknown[2]);
269 VAL_UNKNOWN(objectid_information, unknown[3]);
270 VAL_UNKNOWN(objectid_information, unknown[4]);
271 VAL_UNKNOWN(objectid_information, unknown[5]);
275 #define STR_CHECK(sname, stype, field, flags) do { \
276 s1 = find(sname); \
277 if (s1) { \
278 if (s1->stype.out.field.s && wire_bad_flags(&s1->stype.out.field, flags, cli->transport)) { \
279 printf("(%d) incorrect string termination in %s/%s\n", \
280 __LINE__, #stype, #field); \
281 ret = false; \
283 }} while (0)
285 torture_comment(torture, "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);
293 return ret;