| 1 | /*
|
|---|
| 2 | Unix SMB/CIFS implementation.
|
|---|
| 3 | RAW_FILEINFO_* individual test suite
|
|---|
| 4 | Copyright (C) Andrew Tridgell 2003
|
|---|
| 5 | Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007
|
|---|
| 6 |
|
|---|
| 7 | This program is free software; you can redistribute it and/or modify
|
|---|
| 8 | it under the terms of the GNU General Public License as published by
|
|---|
| 9 | the Free Software Foundation; either version 3 of the License, or
|
|---|
| 10 | (at your option) any later version.
|
|---|
| 11 |
|
|---|
| 12 | This program is distributed in the hope that it will be useful,
|
|---|
| 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|---|
| 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|---|
| 15 | GNU General Public License for more details.
|
|---|
| 16 |
|
|---|
| 17 | You should have received a copy of the GNU General Public License
|
|---|
| 18 | along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|---|
| 19 | */
|
|---|
| 20 |
|
|---|
| 21 | #include "includes.h"
|
|---|
| 22 | #include "torture/torture.h"
|
|---|
| 23 | #include "libcli/raw/libcliraw.h"
|
|---|
| 24 | #include "libcli/raw/raw_proto.h"
|
|---|
| 25 | #include "libcli/libcli.h"
|
|---|
| 26 | #include "torture/util.h"
|
|---|
| 27 | #include "librpc/rpc/dcerpc.h"
|
|---|
| 28 | #include "torture/rpc/rpc.h"
|
|---|
| 29 | #include "torture/raw/proto.h"
|
|---|
| 30 | #include "param/param.h"
|
|---|
| 31 |
|
|---|
| 32 | static struct {
|
|---|
| 33 | const char *name;
|
|---|
| 34 | enum smb_fileinfo_level level;
|
|---|
| 35 | uint_t only_paths:1;
|
|---|
| 36 | uint_t only_handles:1;
|
|---|
| 37 | uint32_t capability_mask;
|
|---|
| 38 | uint_t expected_ipc_access_denied:1;
|
|---|
| 39 | NTSTATUS expected_ipc_fnum_status;
|
|---|
| 40 | NTSTATUS fnum_status, fname_status;
|
|---|
| 41 | union smb_fileinfo fnum_finfo, fname_finfo;
|
|---|
| 42 | } levels[] = {
|
|---|
| 43 | { .name = "GETATTR",
|
|---|
| 44 | .level = RAW_FILEINFO_GETATTR,
|
|---|
| 45 | .only_paths = 1,
|
|---|
| 46 | .only_handles = 0,
|
|---|
| 47 | .expected_ipc_access_denied = 1},
|
|---|
| 48 | { .name ="GETATTRE",
|
|---|
| 49 | .level = RAW_FILEINFO_GETATTRE,
|
|---|
| 50 | .only_paths = 0,
|
|---|
| 51 | .only_handles = 1 },
|
|---|
| 52 | { .name ="STANDARD",
|
|---|
| 53 | .level = RAW_FILEINFO_STANDARD, },
|
|---|
| 54 | { .name ="EA_SIZE",
|
|---|
| 55 | .level = RAW_FILEINFO_EA_SIZE },
|
|---|
| 56 | { .name ="ALL_EAS",
|
|---|
| 57 | .level = RAW_FILEINFO_ALL_EAS,
|
|---|
| 58 | .expected_ipc_fnum_status = NT_STATUS_ACCESS_DENIED,
|
|---|
| 59 | },
|
|---|
| 60 | { .name ="IS_NAME_VALID",
|
|---|
| 61 | .level = RAW_FILEINFO_IS_NAME_VALID,
|
|---|
| 62 | .only_paths = 1,
|
|---|
| 63 | .only_handles = 0 },
|
|---|
| 64 | { .name ="BASIC_INFO",
|
|---|
| 65 | .level = RAW_FILEINFO_BASIC_INFO },
|
|---|
| 66 | { .name ="STANDARD_INFO",
|
|---|
| 67 | .level = RAW_FILEINFO_STANDARD_INFO },
|
|---|
| 68 | { .name ="EA_INFO",
|
|---|
| 69 | .level = RAW_FILEINFO_EA_INFO },
|
|---|
| 70 | { .name ="NAME_INFO",
|
|---|
| 71 | .level = RAW_FILEINFO_NAME_INFO },
|
|---|
| 72 | { .name ="ALL_INFO",
|
|---|
| 73 | .level = RAW_FILEINFO_ALL_INFO },
|
|---|
| 74 | { .name ="ALT_NAME_INFO",
|
|---|
| 75 | .level = RAW_FILEINFO_ALT_NAME_INFO,
|
|---|
| 76 | .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
|
|---|
| 77 | },
|
|---|
| 78 | { .name ="STREAM_INFO",
|
|---|
| 79 | .level = RAW_FILEINFO_STREAM_INFO,
|
|---|
| 80 | .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
|
|---|
| 81 | },
|
|---|
| 82 | { .name ="COMPRESSION_INFO",
|
|---|
| 83 | .level = RAW_FILEINFO_COMPRESSION_INFO,
|
|---|
| 84 | .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
|
|---|
| 85 | },
|
|---|
| 86 | { .name ="UNIX_BASIC_INFO",
|
|---|
| 87 | .level = RAW_FILEINFO_UNIX_BASIC,
|
|---|
| 88 | .only_paths = 0,
|
|---|
| 89 | .only_handles = 0,
|
|---|
| 90 | .capability_mask = CAP_UNIX},
|
|---|
| 91 | { .name ="UNIX_LINK_INFO",
|
|---|
| 92 | .level = RAW_FILEINFO_UNIX_LINK,
|
|---|
| 93 | .only_paths = 0,
|
|---|
| 94 | .only_handles = 0,
|
|---|
| 95 | .capability_mask = CAP_UNIX},
|
|---|
| 96 | { .name ="BASIC_INFORMATION",
|
|---|
| 97 | .level = RAW_FILEINFO_BASIC_INFORMATION },
|
|---|
| 98 | { .name ="STANDARD_INFORMATION",
|
|---|
| 99 | .level = RAW_FILEINFO_STANDARD_INFORMATION },
|
|---|
| 100 | { .name ="INTERNAL_INFORMATION",
|
|---|
| 101 | .level = RAW_FILEINFO_INTERNAL_INFORMATION },
|
|---|
| 102 | { .name ="EA_INFORMATION",
|
|---|
| 103 | .level = RAW_FILEINFO_EA_INFORMATION },
|
|---|
| 104 | { .name = "ACCESS_INFORMATION",
|
|---|
| 105 | .level = RAW_FILEINFO_ACCESS_INFORMATION },
|
|---|
| 106 | { .name = "NAME_INFORMATION",
|
|---|
| 107 | .level = RAW_FILEINFO_NAME_INFORMATION },
|
|---|
| 108 | { .name ="POSITION_INFORMATION",
|
|---|
| 109 | .level = RAW_FILEINFO_POSITION_INFORMATION },
|
|---|
| 110 | { .name ="MODE_INFORMATION",
|
|---|
| 111 | .level = RAW_FILEINFO_MODE_INFORMATION },
|
|---|
| 112 | { .name ="ALIGNMENT_INFORMATION",
|
|---|
| 113 | .level = RAW_FILEINFO_ALIGNMENT_INFORMATION },
|
|---|
| 114 | { .name ="ALL_INFORMATION",
|
|---|
| 115 | .level = RAW_FILEINFO_ALL_INFORMATION },
|
|---|
| 116 | { .name ="ALT_NAME_INFORMATION",
|
|---|
| 117 | .level = RAW_FILEINFO_ALT_NAME_INFORMATION,
|
|---|
| 118 | .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
|
|---|
| 119 | },
|
|---|
| 120 | { .name ="STREAM_INFORMATION",
|
|---|
| 121 | .level = RAW_FILEINFO_STREAM_INFORMATION,
|
|---|
| 122 | .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
|
|---|
| 123 | },
|
|---|
| 124 | { .name = "COMPRESSION_INFORMATION",
|
|---|
| 125 | .level = RAW_FILEINFO_COMPRESSION_INFORMATION,
|
|---|
| 126 | .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
|
|---|
| 127 | },
|
|---|
| 128 | { .name ="NETWORK_OPEN_INFORMATION",
|
|---|
| 129 | .level = RAW_FILEINFO_NETWORK_OPEN_INFORMATION,
|
|---|
| 130 | .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
|
|---|
| 131 | },
|
|---|
| 132 | { .name = "ATTRIBUTE_TAG_INFORMATION",
|
|---|
| 133 | .level = RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION,
|
|---|
| 134 | .expected_ipc_fnum_status = NT_STATUS_INVALID_PARAMETER
|
|---|
| 135 | },
|
|---|
| 136 | { NULL }
|
|---|
| 137 | };
|
|---|
| 138 |
|
|---|
| 139 | /*
|
|---|
| 140 | compare a dos time (2 second resolution) to a nt time
|
|---|
| 141 | */
|
|---|
| 142 | static int dos_nt_time_cmp(time_t t, NTTIME nt)
|
|---|
| 143 | {
|
|---|
| 144 | time_t t2 = nt_time_to_unix(nt);
|
|---|
| 145 | if (abs(t2 - t) <= 2) return 0;
|
|---|
| 146 | return t2 - t;
|
|---|
| 147 | }
|
|---|
| 148 |
|
|---|
| 149 |
|
|---|
| 150 | /*
|
|---|
| 151 | find a level in the levels[] table
|
|---|
| 152 | */
|
|---|
| 153 | static union smb_fileinfo *fnum_find(const char *name)
|
|---|
| 154 | {
|
|---|
| 155 | int i;
|
|---|
| 156 | for (i=0; levels[i].name; i++) {
|
|---|
| 157 | if (NT_STATUS_IS_OK(levels[i].fnum_status) &&
|
|---|
| 158 | strcmp(name, levels[i].name) == 0 &&
|
|---|
| 159 | !levels[i].only_paths) {
|
|---|
| 160 | return &levels[i].fnum_finfo;
|
|---|
| 161 | }
|
|---|
| 162 | }
|
|---|
| 163 | return NULL;
|
|---|
| 164 | }
|
|---|
| 165 |
|
|---|
| 166 | /*
|
|---|
| 167 | find a level in the levels[] table
|
|---|
| 168 | */
|
|---|
| 169 | static union smb_fileinfo *fname_find(bool is_ipc, const char *name)
|
|---|
| 170 | {
|
|---|
| 171 | int i;
|
|---|
| 172 | if (is_ipc) {
|
|---|
| 173 | return NULL;
|
|---|
| 174 | }
|
|---|
| 175 | for (i=0; levels[i].name; i++) {
|
|---|
| 176 | if (NT_STATUS_IS_OK(levels[i].fname_status) &&
|
|---|
| 177 | strcmp(name, levels[i].name) == 0 &&
|
|---|
| 178 | !levels[i].only_handles) {
|
|---|
| 179 | return &levels[i].fname_finfo;
|
|---|
| 180 | }
|
|---|
| 181 | }
|
|---|
| 182 | return NULL;
|
|---|
| 183 | }
|
|---|
| 184 |
|
|---|
| 185 | /* local macros to make the code below more readable */
|
|---|
| 186 | #define VAL_EQUAL(n1, v1, n2, v2) do {if (s1->n1.out.v1 != s2->n2.out.v2) { \
|
|---|
| 187 | printf("%s/%s [%u] != %s/%s [%u] at %s(%d)\n", \
|
|---|
| 188 | #n1, #v1, (uint_t)s1->n1.out.v1, \
|
|---|
| 189 | #n2, #v2, (uint_t)s2->n2.out.v2, \
|
|---|
| 190 | __FILE__, __LINE__); \
|
|---|
| 191 | ret = false; \
|
|---|
| 192 | }} while(0)
|
|---|
| 193 |
|
|---|
| 194 | #define STR_EQUAL(n1, v1, n2, v2) do {if (strcmp_safe(s1->n1.out.v1.s, s2->n2.out.v2.s) || \
|
|---|
| 195 | s1->n1.out.v1.private_length != s2->n2.out.v2.private_length) { \
|
|---|
| 196 | printf("%s/%s [%s/%d] != %s/%s [%s/%d] at %s(%d)\n", \
|
|---|
| 197 | #n1, #v1, s1->n1.out.v1.s, s1->n1.out.v1.private_length, \
|
|---|
| 198 | #n2, #v2, s2->n2.out.v2.s, s2->n2.out.v2.private_length, \
|
|---|
| 199 | __FILE__, __LINE__); \
|
|---|
| 200 | ret = false; \
|
|---|
| 201 | }} while(0)
|
|---|
| 202 |
|
|---|
| 203 | #define STRUCT_EQUAL(n1, v1, n2, v2) do {if (memcmp(&s1->n1.out.v1,&s2->n2.out.v2,sizeof(s1->n1.out.v1))) { \
|
|---|
| 204 | printf("%s/%s != %s/%s at %s(%d)\n", \
|
|---|
| 205 | #n1, #v1, \
|
|---|
| 206 | #n2, #v2, \
|
|---|
| 207 | __FILE__, __LINE__); \
|
|---|
| 208 | ret = false; \
|
|---|
| 209 | }} while(0)
|
|---|
| 210 |
|
|---|
| 211 | /* used to find hints on unknown values - and to make sure
|
|---|
| 212 | we zero-fill */
|
|---|
| 213 | #if 0 /* unused */
|
|---|
| 214 | #define VAL_UNKNOWN(n1, v1) do {if (s1->n1.out.v1 != 0) { \
|
|---|
| 215 | printf("%s/%s non-zero unknown - %u (0x%x) at %s(%d)\n", \
|
|---|
| 216 | #n1, #v1, \
|
|---|
| 217 | (uint_t)s1->n1.out.v1, \
|
|---|
| 218 | (uint_t)s1->n1.out.v1, \
|
|---|
| 219 | __FILE__, __LINE__); \
|
|---|
| 220 | ret = false; \
|
|---|
| 221 | }} while(0)
|
|---|
| 222 | #endif
|
|---|
| 223 |
|
|---|
| 224 | /* basic testing of all RAW_FILEINFO_* calls
|
|---|
| 225 | for each call we test that it succeeds, and where possible test
|
|---|
| 226 | for consistency between the calls.
|
|---|
| 227 | */
|
|---|
| 228 | static bool torture_raw_qfileinfo_internals(struct torture_context *torture,
|
|---|
| 229 | TALLOC_CTX *mem_ctx,
|
|---|
| 230 | struct smbcli_tree *tree,
|
|---|
| 231 | int fnum, const char *fname,
|
|---|
| 232 | bool is_ipc)
|
|---|
| 233 | {
|
|---|
| 234 | int i;
|
|---|
| 235 | bool ret = true;
|
|---|
| 236 | int count;
|
|---|
| 237 | union smb_fileinfo *s1, *s2;
|
|---|
| 238 | NTTIME correct_time;
|
|---|
| 239 | uint64_t correct_size;
|
|---|
| 240 | uint32_t correct_attrib;
|
|---|
| 241 | const char *correct_name;
|
|---|
| 242 | bool skip_streams = false;
|
|---|
| 243 |
|
|---|
| 244 | /* scan all the fileinfo and pathinfo levels */
|
|---|
| 245 | for (i=0; levels[i].name; i++) {
|
|---|
| 246 | if (!levels[i].only_paths) {
|
|---|
| 247 | levels[i].fnum_finfo.generic.level = levels[i].level;
|
|---|
| 248 | levels[i].fnum_finfo.generic.in.file.fnum = fnum;
|
|---|
| 249 | levels[i].fnum_status = smb_raw_fileinfo(tree, mem_ctx,
|
|---|
| 250 | &levels[i].fnum_finfo);
|
|---|
| 251 | }
|
|---|
| 252 |
|
|---|
| 253 | if (!levels[i].only_handles) {
|
|---|
| 254 | levels[i].fname_finfo.generic.level = levels[i].level;
|
|---|
| 255 | levels[i].fname_finfo.generic.in.file.path = talloc_strdup(mem_ctx, fname);
|
|---|
| 256 | levels[i].fname_status = smb_raw_pathinfo(tree, mem_ctx,
|
|---|
| 257 | &levels[i].fname_finfo);
|
|---|
| 258 | }
|
|---|
| 259 | }
|
|---|
| 260 |
|
|---|
| 261 | /* check for completely broken levels */
|
|---|
| 262 | for (count=i=0; levels[i].name; i++) {
|
|---|
| 263 | uint32_t cap = tree->session->transport->negotiate.capabilities;
|
|---|
| 264 | /* see if this server claims to support this level */
|
|---|
| 265 | if ((cap & levels[i].capability_mask) != levels[i].capability_mask) {
|
|---|
| 266 | continue;
|
|---|
| 267 | }
|
|---|
| 268 |
|
|---|
| 269 | if (is_ipc) {
|
|---|
| 270 | if (levels[i].expected_ipc_access_denied && NT_STATUS_EQUAL(NT_STATUS_ACCESS_DENIED, levels[i].fname_status)) {
|
|---|
| 271 | } else if (!levels[i].only_handles && !NT_STATUS_EQUAL(NT_STATUS_INVALID_DEVICE_REQUEST, levels[i].fname_status)) {
|
|---|
| 272 | printf("ERROR: fname level %s failed, expected NT_STATUS_INVALID_DEVICE_REQUEST - %s\n",
|
|---|
| 273 | levels[i].name, nt_errstr(levels[i].fname_status));
|
|---|
| 274 | count++;
|
|---|
| 275 | }
|
|---|
| 276 | if (!levels[i].only_paths && !NT_STATUS_EQUAL(levels[i].expected_ipc_fnum_status, levels[i].fnum_status)) {
|
|---|
| 277 | printf("ERROR: fnum level %s failed, expected %s - %s\n",
|
|---|
| 278 | levels[i].name, nt_errstr(levels[i].expected_ipc_fnum_status),
|
|---|
| 279 | nt_errstr(levels[i].fnum_status));
|
|---|
| 280 | count++;
|
|---|
| 281 | }
|
|---|
| 282 | } else {
|
|---|
| 283 | if (!levels[i].only_paths && !NT_STATUS_IS_OK(levels[i].fnum_status)) {
|
|---|
| 284 | printf("ERROR: fnum level %s failed - %s\n",
|
|---|
| 285 | levels[i].name, nt_errstr(levels[i].fnum_status));
|
|---|
| 286 | count++;
|
|---|
| 287 | }
|
|---|
| 288 | if (!levels[i].only_handles && !NT_STATUS_IS_OK(levels[i].fname_status)) {
|
|---|
| 289 | printf("ERROR: fname level %s failed - %s\n",
|
|---|
| 290 | levels[i].name, nt_errstr(levels[i].fname_status));
|
|---|
| 291 | count++;
|
|---|
| 292 | }
|
|---|
| 293 | }
|
|---|
| 294 |
|
|---|
| 295 | }
|
|---|
| 296 |
|
|---|
| 297 | if (count != 0) {
|
|---|
| 298 | ret = false;
|
|---|
| 299 | printf("%d levels failed\n", count);
|
|---|
| 300 | if (count > 35) {
|
|---|
| 301 | torture_fail(torture, "too many level failures - giving up");
|
|---|
| 302 | }
|
|---|
| 303 | }
|
|---|
| 304 |
|
|---|
| 305 | /* see if we can do streams */
|
|---|
| 306 | s1 = fnum_find("STREAM_INFO");
|
|---|
| 307 | if (!s1 || s1->stream_info.out.num_streams == 0) {
|
|---|
| 308 | if (!is_ipc) {
|
|---|
| 309 | printf("STREAM_INFO broken (%d) - skipping streams checks\n",
|
|---|
| 310 | s1 ? s1->stream_info.out.num_streams : -1);
|
|---|
| 311 | }
|
|---|
| 312 | skip_streams = true;
|
|---|
| 313 | }
|
|---|
| 314 |
|
|---|
| 315 |
|
|---|
| 316 | /* this code is incredibly repititive but doesn't lend itself to loops, so
|
|---|
| 317 | we use lots of macros to make it less painful */
|
|---|
| 318 |
|
|---|
| 319 | /* first off we check the levels that are supposed to be aliases. It will be quite rare for
|
|---|
| 320 | this code to fail, but we need to check it for completeness */
|
|---|
| 321 |
|
|---|
| 322 |
|
|---|
| 323 |
|
|---|
| 324 | #define ALIAS_CHECK(sname1, sname2) \
|
|---|
| 325 | do { \
|
|---|
| 326 | s1 = fnum_find(sname1); s2 = fnum_find(sname2); \
|
|---|
| 327 | if (s1 && s2) { INFO_CHECK } \
|
|---|
| 328 | s1 = fname_find(is_ipc, sname1); s2 = fname_find(is_ipc, sname2); \
|
|---|
| 329 | if (s1 && s2) { INFO_CHECK } \
|
|---|
| 330 | s1 = fnum_find(sname1); s2 = fname_find(is_ipc, sname2); \
|
|---|
| 331 | if (s1 && s2) { INFO_CHECK } \
|
|---|
| 332 | } while (0)
|
|---|
| 333 |
|
|---|
| 334 | #define INFO_CHECK \
|
|---|
| 335 | STRUCT_EQUAL(basic_info, create_time, basic_info, create_time); \
|
|---|
| 336 | STRUCT_EQUAL(basic_info, access_time, basic_info, access_time); \
|
|---|
| 337 | STRUCT_EQUAL(basic_info, write_time, basic_info, write_time); \
|
|---|
| 338 | STRUCT_EQUAL(basic_info, change_time, basic_info, change_time); \
|
|---|
| 339 | VAL_EQUAL (basic_info, attrib, basic_info, attrib);
|
|---|
| 340 |
|
|---|
| 341 | ALIAS_CHECK("BASIC_INFO", "BASIC_INFORMATION");
|
|---|
| 342 |
|
|---|
| 343 | #undef INFO_CHECK
|
|---|
| 344 | #define INFO_CHECK \
|
|---|
| 345 | VAL_EQUAL(standard_info, alloc_size, standard_info, alloc_size); \
|
|---|
| 346 | VAL_EQUAL(standard_info, size, standard_info, size); \
|
|---|
| 347 | VAL_EQUAL(standard_info, nlink, standard_info, nlink); \
|
|---|
| 348 | VAL_EQUAL(standard_info, delete_pending, standard_info, delete_pending); \
|
|---|
| 349 | VAL_EQUAL(standard_info, directory, standard_info, directory);
|
|---|
| 350 |
|
|---|
| 351 | ALIAS_CHECK("STANDARD_INFO", "STANDARD_INFORMATION");
|
|---|
| 352 |
|
|---|
| 353 | #undef INFO_CHECK
|
|---|
| 354 | #define INFO_CHECK \
|
|---|
| 355 | VAL_EQUAL(ea_info, ea_size, ea_info, ea_size);
|
|---|
| 356 |
|
|---|
| 357 | ALIAS_CHECK("EA_INFO", "EA_INFORMATION");
|
|---|
| 358 |
|
|---|
| 359 | #undef INFO_CHECK
|
|---|
| 360 | #define INFO_CHECK \
|
|---|
| 361 | STR_EQUAL(name_info, fname, name_info, fname);
|
|---|
| 362 |
|
|---|
| 363 | ALIAS_CHECK("NAME_INFO", "NAME_INFORMATION");
|
|---|
| 364 |
|
|---|
| 365 | #undef INFO_CHECK
|
|---|
| 366 | #define INFO_CHECK \
|
|---|
| 367 | STRUCT_EQUAL(all_info, create_time, all_info, create_time); \
|
|---|
| 368 | STRUCT_EQUAL(all_info, access_time, all_info, access_time); \
|
|---|
| 369 | STRUCT_EQUAL(all_info, write_time, all_info, write_time); \
|
|---|
| 370 | STRUCT_EQUAL(all_info, change_time, all_info, change_time); \
|
|---|
| 371 | VAL_EQUAL(all_info, attrib, all_info, attrib); \
|
|---|
| 372 | VAL_EQUAL(all_info, alloc_size, all_info, alloc_size); \
|
|---|
| 373 | VAL_EQUAL(all_info, size, all_info, size); \
|
|---|
| 374 | VAL_EQUAL(all_info, nlink, all_info, nlink); \
|
|---|
| 375 | VAL_EQUAL(all_info, delete_pending, all_info, delete_pending); \
|
|---|
| 376 | VAL_EQUAL(all_info, directory, all_info, directory); \
|
|---|
| 377 | VAL_EQUAL(all_info, ea_size, all_info, ea_size); \
|
|---|
| 378 | STR_EQUAL(all_info, fname, all_info, fname);
|
|---|
| 379 |
|
|---|
| 380 | ALIAS_CHECK("ALL_INFO", "ALL_INFORMATION");
|
|---|
| 381 |
|
|---|
| 382 | #undef INFO_CHECK
|
|---|
| 383 | #define INFO_CHECK \
|
|---|
| 384 | VAL_EQUAL(compression_info, compressed_size,compression_info, compressed_size); \
|
|---|
| 385 | VAL_EQUAL(compression_info, format, compression_info, format); \
|
|---|
| 386 | VAL_EQUAL(compression_info, unit_shift, compression_info, unit_shift); \
|
|---|
| 387 | VAL_EQUAL(compression_info, chunk_shift, compression_info, chunk_shift); \
|
|---|
| 388 | VAL_EQUAL(compression_info, cluster_shift, compression_info, cluster_shift);
|
|---|
| 389 |
|
|---|
| 390 | ALIAS_CHECK("COMPRESSION_INFO", "COMPRESSION_INFORMATION");
|
|---|
| 391 |
|
|---|
| 392 |
|
|---|
| 393 | #undef INFO_CHECK
|
|---|
| 394 | #define INFO_CHECK \
|
|---|
| 395 | STR_EQUAL(alt_name_info, fname, alt_name_info, fname);
|
|---|
| 396 |
|
|---|
| 397 | ALIAS_CHECK("ALT_NAME_INFO", "ALT_NAME_INFORMATION");
|
|---|
| 398 |
|
|---|
| 399 |
|
|---|
| 400 | #define TIME_CHECK_NT(sname, stype, tfield) do { \
|
|---|
| 401 | s1 = fnum_find(sname); \
|
|---|
| 402 | if (s1 && memcmp(&s1->stype.out.tfield, &correct_time, sizeof(correct_time)) != 0) { \
|
|---|
| 403 | printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
|---|
| 404 | nt_time_string(mem_ctx, s1->stype.out.tfield), \
|
|---|
| 405 | nt_time_string(mem_ctx, correct_time)); \
|
|---|
| 406 | ret = false; \
|
|---|
| 407 | } \
|
|---|
| 408 | s1 = fname_find(is_ipc, sname); \
|
|---|
| 409 | if (s1 && memcmp(&s1->stype.out.tfield, &correct_time, sizeof(correct_time)) != 0) { \
|
|---|
| 410 | printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
|---|
| 411 | nt_time_string(mem_ctx, s1->stype.out.tfield), \
|
|---|
| 412 | nt_time_string(mem_ctx, correct_time)); \
|
|---|
| 413 | ret = false; \
|
|---|
| 414 | }} while (0)
|
|---|
| 415 |
|
|---|
| 416 | #define TIME_CHECK_DOS(sname, stype, tfield) do { \
|
|---|
| 417 | s1 = fnum_find(sname); \
|
|---|
| 418 | if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
|
|---|
| 419 | printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
|---|
| 420 | timestring(mem_ctx, s1->stype.out.tfield), \
|
|---|
| 421 | nt_time_string(mem_ctx, correct_time)); \
|
|---|
| 422 | ret = false; \
|
|---|
| 423 | } \
|
|---|
| 424 | s1 = fname_find(is_ipc, sname); \
|
|---|
| 425 | if (s1 && dos_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
|
|---|
| 426 | printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
|---|
| 427 | timestring(mem_ctx, s1->stype.out.tfield), \
|
|---|
| 428 | nt_time_string(mem_ctx, correct_time)); \
|
|---|
| 429 | ret = false; \
|
|---|
| 430 | }} while (0)
|
|---|
| 431 |
|
|---|
| 432 | #if 0 /* unused */
|
|---|
| 433 | #define TIME_CHECK_UNX(sname, stype, tfield) do { \
|
|---|
| 434 | s1 = fnum_find(sname); \
|
|---|
| 435 | if (s1 && unx_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
|
|---|
| 436 | printf("(%d) handle %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
|---|
| 437 | timestring(mem_ctx, s1->stype.out.tfield), \
|
|---|
| 438 | nt_time_string(mem_ctx, correct_time)); \
|
|---|
| 439 | ret = false; \
|
|---|
| 440 | } \
|
|---|
| 441 | s1 = fname_find(is_ipc, sname); \
|
|---|
| 442 | if (s1 && unx_nt_time_cmp(s1->stype.out.tfield, correct_time) != 0) { \
|
|---|
| 443 | printf("(%d) path %s/%s incorrect - %s should be %s\n", __LINE__, #stype, #tfield, \
|
|---|
| 444 | timestring(mem_ctx, s1->stype.out.tfield), \
|
|---|
| 445 | nt_time_string(mem_ctx, correct_time)); \
|
|---|
| 446 | ret = false; \
|
|---|
| 447 | }} while (0)
|
|---|
| 448 | #endif
|
|---|
| 449 |
|
|---|
| 450 | /* now check that all the times that are supposed to be equal are correct */
|
|---|
| 451 | s1 = fnum_find("BASIC_INFO");
|
|---|
| 452 | correct_time = s1->basic_info.out.create_time;
|
|---|
| 453 | torture_comment(torture, "create_time: %s\n", nt_time_string(mem_ctx, correct_time));
|
|---|
| 454 |
|
|---|
| 455 | TIME_CHECK_NT ("BASIC_INFO", basic_info, create_time);
|
|---|
| 456 | TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, create_time);
|
|---|
| 457 | TIME_CHECK_DOS("GETATTRE", getattre, create_time);
|
|---|
| 458 | TIME_CHECK_DOS("STANDARD", standard, create_time);
|
|---|
| 459 | TIME_CHECK_DOS("EA_SIZE", ea_size, create_time);
|
|---|
| 460 | TIME_CHECK_NT ("ALL_INFO", all_info, create_time);
|
|---|
| 461 | TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, create_time);
|
|---|
| 462 |
|
|---|
| 463 | s1 = fnum_find("BASIC_INFO");
|
|---|
| 464 | correct_time = s1->basic_info.out.access_time;
|
|---|
| 465 | torture_comment(torture, "access_time: %s\n", nt_time_string(mem_ctx, correct_time));
|
|---|
| 466 |
|
|---|
| 467 | TIME_CHECK_NT ("BASIC_INFO", basic_info, access_time);
|
|---|
| 468 | TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, access_time);
|
|---|
| 469 | TIME_CHECK_DOS("GETATTRE", getattre, access_time);
|
|---|
| 470 | TIME_CHECK_DOS("STANDARD", standard, access_time);
|
|---|
| 471 | TIME_CHECK_DOS("EA_SIZE", ea_size, access_time);
|
|---|
| 472 | TIME_CHECK_NT ("ALL_INFO", all_info, access_time);
|
|---|
| 473 | TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, access_time);
|
|---|
| 474 |
|
|---|
| 475 | s1 = fnum_find("BASIC_INFO");
|
|---|
| 476 | correct_time = s1->basic_info.out.write_time;
|
|---|
| 477 | torture_comment(torture, "write_time : %s\n", nt_time_string(mem_ctx, correct_time));
|
|---|
| 478 |
|
|---|
| 479 | TIME_CHECK_NT ("BASIC_INFO", basic_info, write_time);
|
|---|
| 480 | TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, write_time);
|
|---|
| 481 | TIME_CHECK_DOS("GETATTR", getattr, write_time);
|
|---|
| 482 | TIME_CHECK_DOS("GETATTRE", getattre, write_time);
|
|---|
| 483 | TIME_CHECK_DOS("STANDARD", standard, write_time);
|
|---|
| 484 | TIME_CHECK_DOS("EA_SIZE", ea_size, write_time);
|
|---|
| 485 | TIME_CHECK_NT ("ALL_INFO", all_info, write_time);
|
|---|
| 486 | TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, write_time);
|
|---|
| 487 |
|
|---|
| 488 | s1 = fnum_find("BASIC_INFO");
|
|---|
| 489 | correct_time = s1->basic_info.out.change_time;
|
|---|
| 490 | torture_comment(torture, "change_time: %s\n", nt_time_string(mem_ctx, correct_time));
|
|---|
| 491 |
|
|---|
| 492 | TIME_CHECK_NT ("BASIC_INFO", basic_info, change_time);
|
|---|
| 493 | TIME_CHECK_NT ("BASIC_INFORMATION", basic_info, change_time);
|
|---|
| 494 | TIME_CHECK_NT ("ALL_INFO", all_info, change_time);
|
|---|
| 495 | TIME_CHECK_NT ("NETWORK_OPEN_INFORMATION", network_open_information, change_time);
|
|---|
| 496 |
|
|---|
| 497 |
|
|---|
| 498 | #define SIZE_CHECK(sname, stype, tfield) do { \
|
|---|
| 499 | s1 = fnum_find(sname); \
|
|---|
| 500 | if (s1 && s1->stype.out.tfield != correct_size) { \
|
|---|
| 501 | printf("(%d) handle %s/%s incorrect - %u should be %u\n", __LINE__, #stype, #tfield, \
|
|---|
| 502 | (uint_t)s1->stype.out.tfield, \
|
|---|
| 503 | (uint_t)correct_size); \
|
|---|
| 504 | ret = false; \
|
|---|
| 505 | } \
|
|---|
| 506 | s1 = fname_find(is_ipc, sname); \
|
|---|
| 507 | if (s1 && s1->stype.out.tfield != correct_size) { \
|
|---|
| 508 | printf("(%d) path %s/%s incorrect - %u should be %u\n", __LINE__, #stype, #tfield, \
|
|---|
| 509 | (uint_t)s1->stype.out.tfield, \
|
|---|
| 510 | (uint_t)correct_size); \
|
|---|
| 511 | ret = false; \
|
|---|
| 512 | }} while (0)
|
|---|
| 513 |
|
|---|
| 514 | s1 = fnum_find("STANDARD_INFO");
|
|---|
| 515 | correct_size = s1->standard_info.out.size;
|
|---|
| 516 | torture_comment(torture, "size: %u\n", (uint_t)correct_size);
|
|---|
| 517 |
|
|---|
| 518 | SIZE_CHECK("GETATTR", getattr, size);
|
|---|
| 519 | SIZE_CHECK("GETATTRE", getattre, size);
|
|---|
| 520 | SIZE_CHECK("STANDARD", standard, size);
|
|---|
| 521 | SIZE_CHECK("EA_SIZE", ea_size, size);
|
|---|
| 522 | SIZE_CHECK("STANDARD_INFO", standard_info, size);
|
|---|
| 523 | SIZE_CHECK("STANDARD_INFORMATION", standard_info, size);
|
|---|
| 524 | SIZE_CHECK("ALL_INFO", all_info, size);
|
|---|
| 525 | SIZE_CHECK("ALL_INFORMATION", all_info, size);
|
|---|
| 526 | SIZE_CHECK("COMPRESSION_INFO", compression_info, compressed_size);
|
|---|
| 527 | SIZE_CHECK("COMPRESSION_INFORMATION", compression_info, compressed_size);
|
|---|
| 528 | SIZE_CHECK("NETWORK_OPEN_INFORMATION", network_open_information, size);
|
|---|
| 529 | if (!skip_streams) {
|
|---|
| 530 | SIZE_CHECK("STREAM_INFO", stream_info, streams[0].size);
|
|---|
| 531 | SIZE_CHECK("STREAM_INFORMATION", stream_info, streams[0].size);
|
|---|
| 532 | }
|
|---|
| 533 |
|
|---|
| 534 |
|
|---|
| 535 | s1 = fnum_find("STANDARD_INFO");
|
|---|
| 536 | correct_size = s1->standard_info.out.alloc_size;
|
|---|
| 537 | torture_comment(torture, "alloc_size: %u\n", (uint_t)correct_size);
|
|---|
| 538 |
|
|---|
| 539 | SIZE_CHECK("GETATTRE", getattre, alloc_size);
|
|---|
| 540 | SIZE_CHECK("STANDARD", standard, alloc_size);
|
|---|
| 541 | SIZE_CHECK("EA_SIZE", ea_size, alloc_size);
|
|---|
| 542 | SIZE_CHECK("STANDARD_INFO", standard_info, alloc_size);
|
|---|
| 543 | SIZE_CHECK("STANDARD_INFORMATION", standard_info, alloc_size);
|
|---|
| 544 | SIZE_CHECK("ALL_INFO", all_info, alloc_size);
|
|---|
| 545 | SIZE_CHECK("ALL_INFORMATION", all_info, alloc_size);
|
|---|
| 546 | SIZE_CHECK("NETWORK_OPEN_INFORMATION", network_open_information, alloc_size);
|
|---|
| 547 | if (!skip_streams) {
|
|---|
| 548 | SIZE_CHECK("STREAM_INFO", stream_info, streams[0].alloc_size);
|
|---|
| 549 | SIZE_CHECK("STREAM_INFORMATION", stream_info, streams[0].alloc_size);
|
|---|
| 550 | }
|
|---|
| 551 |
|
|---|
| 552 | #define ATTRIB_CHECK(sname, stype, tfield) do { \
|
|---|
| 553 | s1 = fnum_find(sname); \
|
|---|
| 554 | if (s1 && s1->stype.out.tfield != correct_attrib) { \
|
|---|
| 555 | printf("(%d) handle %s/%s incorrect - 0x%x should be 0x%x\n", __LINE__, #stype, #tfield, \
|
|---|
| 556 | (uint_t)s1->stype.out.tfield, \
|
|---|
| 557 | (uint_t)correct_attrib); \
|
|---|
| 558 | ret = false; \
|
|---|
| 559 | } \
|
|---|
| 560 | s1 = fname_find(is_ipc, sname); \
|
|---|
| 561 | if (s1 && s1->stype.out.tfield != correct_attrib) { \
|
|---|
| 562 | printf("(%d) path %s/%s incorrect - 0x%x should be 0x%x\n", __LINE__, #stype, #tfield, \
|
|---|
| 563 | (uint_t)s1->stype.out.tfield, \
|
|---|
| 564 | (uint_t)correct_attrib); \
|
|---|
| 565 | ret = false; \
|
|---|
| 566 | }} while (0)
|
|---|
| 567 |
|
|---|
| 568 | s1 = fnum_find("BASIC_INFO");
|
|---|
| 569 | correct_attrib = s1->basic_info.out.attrib;
|
|---|
| 570 | torture_comment(torture, "attrib: 0x%x\n", (uint_t)correct_attrib);
|
|---|
| 571 |
|
|---|
| 572 | ATTRIB_CHECK("GETATTR", getattr, attrib);
|
|---|
| 573 | if (!is_ipc) {
|
|---|
| 574 | ATTRIB_CHECK("GETATTRE", getattre, attrib);
|
|---|
| 575 | ATTRIB_CHECK("STANDARD", standard, attrib);
|
|---|
| 576 | ATTRIB_CHECK("EA_SIZE", ea_size, attrib);
|
|---|
| 577 | }
|
|---|
| 578 | ATTRIB_CHECK("BASIC_INFO", basic_info, attrib);
|
|---|
| 579 | ATTRIB_CHECK("BASIC_INFORMATION", basic_info, attrib);
|
|---|
| 580 | ATTRIB_CHECK("ALL_INFO", all_info, attrib);
|
|---|
| 581 | ATTRIB_CHECK("ALL_INFORMATION", all_info, attrib);
|
|---|
| 582 | ATTRIB_CHECK("NETWORK_OPEN_INFORMATION", network_open_information, attrib);
|
|---|
| 583 | ATTRIB_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, attrib);
|
|---|
| 584 |
|
|---|
| 585 | correct_name = fname;
|
|---|
| 586 | torture_comment(torture, "name: %s\n", correct_name);
|
|---|
| 587 |
|
|---|
| 588 | #define NAME_CHECK(sname, stype, tfield, flags) do { \
|
|---|
| 589 | s1 = fnum_find(sname); \
|
|---|
| 590 | if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \
|
|---|
| 591 | wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \
|
|---|
| 592 | printf("(%d) handle %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield, \
|
|---|
| 593 | s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \
|
|---|
| 594 | ret = false; \
|
|---|
| 595 | } \
|
|---|
| 596 | s1 = fname_find(is_ipc, sname); \
|
|---|
| 597 | if (s1 && (strcmp_safe(s1->stype.out.tfield.s, correct_name) != 0 || \
|
|---|
| 598 | wire_bad_flags(&s1->stype.out.tfield, flags, tree->session->transport))) { \
|
|---|
| 599 | printf("(%d) path %s/%s incorrect - '%s/%d'\n", __LINE__, #stype, #tfield, \
|
|---|
| 600 | s1->stype.out.tfield.s, s1->stype.out.tfield.private_length); \
|
|---|
| 601 | ret = false; \
|
|---|
| 602 | }} while (0)
|
|---|
| 603 |
|
|---|
| 604 | NAME_CHECK("NAME_INFO", name_info, fname, STR_UNICODE);
|
|---|
| 605 | NAME_CHECK("NAME_INFORMATION", name_info, fname, STR_UNICODE);
|
|---|
| 606 |
|
|---|
| 607 | /* the ALL_INFO file name is the full path on the filesystem */
|
|---|
| 608 | s1 = fnum_find("ALL_INFO");
|
|---|
| 609 | if (s1 && !s1->all_info.out.fname.s) {
|
|---|
| 610 | torture_fail(torture, "ALL_INFO didn't give a filename");
|
|---|
| 611 | }
|
|---|
| 612 | if (s1 && s1->all_info.out.fname.s) {
|
|---|
| 613 | char *p = strrchr(s1->all_info.out.fname.s, '\\');
|
|---|
| 614 | if (!p) {
|
|---|
| 615 | printf("Not a full path in all_info/fname? - '%s'\n",
|
|---|
| 616 | s1->all_info.out.fname.s);
|
|---|
| 617 | ret = false;
|
|---|
| 618 | } else {
|
|---|
| 619 | if (strcmp_safe(correct_name, p) != 0) {
|
|---|
| 620 | printf("incorrect basename in all_info/fname - '%s'\n",
|
|---|
| 621 | s1->all_info.out.fname.s);
|
|---|
| 622 | ret = false;
|
|---|
| 623 | }
|
|---|
| 624 | }
|
|---|
| 625 | if (wire_bad_flags(&s1->all_info.out.fname, STR_UNICODE, tree->session->transport)) {
|
|---|
| 626 | printf("Should not null terminate all_info/fname\n");
|
|---|
| 627 | ret = false;
|
|---|
| 628 | }
|
|---|
| 629 | }
|
|---|
| 630 |
|
|---|
| 631 | s1 = fnum_find("ALT_NAME_INFO");
|
|---|
| 632 | if (s1) {
|
|---|
| 633 | correct_name = s1->alt_name_info.out.fname.s;
|
|---|
| 634 | torture_comment(torture, "alt_name: %s\n", correct_name);
|
|---|
| 635 |
|
|---|
| 636 | NAME_CHECK("ALT_NAME_INFO", alt_name_info, fname, STR_UNICODE);
|
|---|
| 637 | NAME_CHECK("ALT_NAME_INFORMATION", alt_name_info, fname, STR_UNICODE);
|
|---|
| 638 |
|
|---|
| 639 | /* and make sure we can open by alternate name */
|
|---|
| 640 | smbcli_close(tree, fnum);
|
|---|
| 641 | fnum = smbcli_nt_create_full(tree, correct_name, 0,
|
|---|
| 642 | SEC_RIGHTS_FILE_ALL,
|
|---|
| 643 | FILE_ATTRIBUTE_NORMAL,
|
|---|
| 644 | NTCREATEX_SHARE_ACCESS_DELETE|
|
|---|
| 645 | NTCREATEX_SHARE_ACCESS_READ|
|
|---|
| 646 | NTCREATEX_SHARE_ACCESS_WRITE,
|
|---|
| 647 | NTCREATEX_DISP_OVERWRITE_IF,
|
|---|
| 648 | 0, 0);
|
|---|
| 649 | if (fnum == -1) {
|
|---|
| 650 | printf("Unable to open by alt_name - %s\n", smbcli_errstr(tree));
|
|---|
| 651 | ret = false;
|
|---|
| 652 | }
|
|---|
| 653 |
|
|---|
| 654 | if (!skip_streams) {
|
|---|
| 655 | correct_name = "::$DATA";
|
|---|
| 656 | torture_comment(torture, "stream_name: %s\n", correct_name);
|
|---|
| 657 |
|
|---|
| 658 | NAME_CHECK("STREAM_INFO", stream_info, streams[0].stream_name, STR_UNICODE);
|
|---|
| 659 | NAME_CHECK("STREAM_INFORMATION", stream_info, streams[0].stream_name, STR_UNICODE);
|
|---|
| 660 | }
|
|---|
| 661 | }
|
|---|
| 662 |
|
|---|
| 663 | /* make sure the EAs look right */
|
|---|
| 664 | s1 = fnum_find("ALL_EAS");
|
|---|
| 665 | s2 = fnum_find("ALL_INFO");
|
|---|
| 666 | if (s1) {
|
|---|
| 667 | for (i=0;i<s1->all_eas.out.num_eas;i++) {
|
|---|
| 668 | printf(" flags=%d %s=%*.*s\n",
|
|---|
| 669 | s1->all_eas.out.eas[i].flags,
|
|---|
| 670 | s1->all_eas.out.eas[i].name.s,
|
|---|
| 671 | (int)s1->all_eas.out.eas[i].value.length,
|
|---|
| 672 | (int)s1->all_eas.out.eas[i].value.length,
|
|---|
| 673 | s1->all_eas.out.eas[i].value.data);
|
|---|
| 674 | }
|
|---|
| 675 | }
|
|---|
| 676 | if (s1 && s2) {
|
|---|
| 677 | if (s1->all_eas.out.num_eas == 0) {
|
|---|
| 678 | if (s2->all_info.out.ea_size != 0) {
|
|---|
| 679 | printf("ERROR: num_eas==0 but fnum all_info.out.ea_size == %d\n",
|
|---|
| 680 | s2->all_info.out.ea_size);
|
|---|
| 681 | }
|
|---|
| 682 | } else {
|
|---|
| 683 | if (s2->all_info.out.ea_size !=
|
|---|
| 684 | ea_list_size(s1->all_eas.out.num_eas, s1->all_eas.out.eas)) {
|
|---|
| 685 | printf("ERROR: ea_list_size=%d != fnum all_info.out.ea_size=%d\n",
|
|---|
| 686 | (int)ea_list_size(s1->all_eas.out.num_eas, s1->all_eas.out.eas),
|
|---|
| 687 | (int)s2->all_info.out.ea_size);
|
|---|
| 688 | }
|
|---|
| 689 | }
|
|---|
| 690 | }
|
|---|
| 691 | s2 = fname_find(is_ipc, "ALL_EAS");
|
|---|
| 692 | if (s2) {
|
|---|
| 693 | VAL_EQUAL(all_eas, num_eas, all_eas, num_eas);
|
|---|
| 694 | for (i=0;i<s1->all_eas.out.num_eas;i++) {
|
|---|
| 695 | VAL_EQUAL(all_eas, eas[i].flags, all_eas, eas[i].flags);
|
|---|
| 696 | STR_EQUAL(all_eas, eas[i].name, all_eas, eas[i].name);
|
|---|
| 697 | VAL_EQUAL(all_eas, eas[i].value.length, all_eas, eas[i].value.length);
|
|---|
| 698 | }
|
|---|
| 699 | }
|
|---|
| 700 |
|
|---|
| 701 | #define VAL_CHECK(sname1, stype1, tfield1, sname2, stype2, tfield2) do { \
|
|---|
| 702 | s1 = fnum_find(sname1); s2 = fnum_find(sname2); \
|
|---|
| 703 | if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
|
|---|
| 704 | printf("(%d) handle %s/%s != %s/%s - 0x%x vs 0x%x\n", __LINE__, \
|
|---|
| 705 | #stype1, #tfield1, #stype2, #tfield2, \
|
|---|
| 706 | s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
|
|---|
| 707 | ret = false; \
|
|---|
| 708 | } \
|
|---|
| 709 | s1 = fname_find(is_ipc, sname1); s2 = fname_find(is_ipc, sname2); \
|
|---|
| 710 | if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
|
|---|
| 711 | printf("(%d) path %s/%s != %s/%s - 0x%x vs 0x%x\n", __LINE__, \
|
|---|
| 712 | #stype1, #tfield1, #stype2, #tfield2, \
|
|---|
| 713 | s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
|
|---|
| 714 | ret = false; \
|
|---|
| 715 | } \
|
|---|
| 716 | s1 = fnum_find(sname1); s2 = fname_find(is_ipc, sname2); \
|
|---|
| 717 | if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
|
|---|
| 718 | printf("(%d) handle %s/%s != path %s/%s - 0x%x vs 0x%x\n", __LINE__, \
|
|---|
| 719 | #stype1, #tfield1, #stype2, #tfield2, \
|
|---|
| 720 | s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
|
|---|
| 721 | ret = false; \
|
|---|
| 722 | } \
|
|---|
| 723 | s1 = fname_find(is_ipc, sname1); s2 = fnum_find(sname2); \
|
|---|
| 724 | if (s1 && s2 && s1->stype1.out.tfield1 != s2->stype2.out.tfield2) { \
|
|---|
| 725 | printf("(%d) path %s/%s != handle %s/%s - 0x%x vs 0x%x\n", __LINE__, \
|
|---|
| 726 | #stype1, #tfield1, #stype2, #tfield2, \
|
|---|
| 727 | s1->stype1.out.tfield1, s2->stype2.out.tfield2); \
|
|---|
| 728 | ret = false; \
|
|---|
| 729 | }} while (0)
|
|---|
| 730 |
|
|---|
| 731 | VAL_CHECK("STANDARD_INFO", standard_info, delete_pending,
|
|---|
| 732 | "ALL_INFO", all_info, delete_pending);
|
|---|
| 733 | VAL_CHECK("STANDARD_INFO", standard_info, directory,
|
|---|
| 734 | "ALL_INFO", all_info, directory);
|
|---|
| 735 | VAL_CHECK("STANDARD_INFO", standard_info, nlink,
|
|---|
| 736 | "ALL_INFO", all_info, nlink);
|
|---|
| 737 | s1 = fnum_find("BASIC_INFO");
|
|---|
| 738 | if (s1 && is_ipc) {
|
|---|
| 739 | if (s1->basic_info.out.attrib != FILE_ATTRIBUTE_NORMAL) {
|
|---|
| 740 | printf("(%d) attrib basic_info/nlink incorrect - %d should be %d\n", __LINE__, s1->basic_info.out.attrib, FILE_ATTRIBUTE_NORMAL);
|
|---|
| 741 | ret = false;
|
|---|
| 742 | }
|
|---|
| 743 | }
|
|---|
| 744 | s1 = fnum_find("STANDARD_INFO");
|
|---|
| 745 | if (s1 && is_ipc) {
|
|---|
| 746 | if (s1->standard_info.out.nlink != 1) {
|
|---|
| 747 | printf("(%d) nlinks standard_info/nlink incorrect - %d should be 1\n", __LINE__, s1->standard_info.out.nlink);
|
|---|
| 748 | ret = false;
|
|---|
| 749 | }
|
|---|
| 750 | if (s1->standard_info.out.delete_pending != 1) {
|
|---|
| 751 | printf("(%d) nlinks standard_info/delete_pending incorrect - %d should be 1\n", __LINE__, s1->standard_info.out.delete_pending);
|
|---|
| 752 | ret = false;
|
|---|
| 753 | }
|
|---|
| 754 | }
|
|---|
| 755 | VAL_CHECK("EA_INFO", ea_info, ea_size,
|
|---|
| 756 | "ALL_INFO", all_info, ea_size);
|
|---|
| 757 | if (!is_ipc) {
|
|---|
| 758 | VAL_CHECK("EA_SIZE", ea_size, ea_size,
|
|---|
| 759 | "ALL_INFO", all_info, ea_size);
|
|---|
| 760 | }
|
|---|
| 761 |
|
|---|
| 762 | #define NAME_PATH_CHECK(sname, stype, field) do { \
|
|---|
| 763 | s1 = fname_find(is_ipc, sname); s2 = fnum_find(sname); \
|
|---|
| 764 | if (s1 && s2) { \
|
|---|
| 765 | VAL_EQUAL(stype, field, stype, field); \
|
|---|
| 766 | } \
|
|---|
| 767 | } while (0)
|
|---|
| 768 |
|
|---|
| 769 |
|
|---|
| 770 | s1 = fnum_find("INTERNAL_INFORMATION");
|
|---|
| 771 | if (s1) {
|
|---|
| 772 | torture_comment(torture, "file_id=%.0f\n", (double)s1->internal_information.out.file_id);
|
|---|
| 773 | }
|
|---|
| 774 |
|
|---|
| 775 | NAME_PATH_CHECK("INTERNAL_INFORMATION", internal_information, file_id);
|
|---|
| 776 | NAME_PATH_CHECK("POSITION_INFORMATION", position_information, position);
|
|---|
| 777 | if (s1 && s2) {
|
|---|
| 778 | printf("fnum pos = %.0f, fname pos = %.0f\n",
|
|---|
| 779 | (double)s2->position_information.out.position,
|
|---|
| 780 | (double)s1->position_information.out.position );
|
|---|
| 781 | }
|
|---|
| 782 | NAME_PATH_CHECK("MODE_INFORMATION", mode_information, mode);
|
|---|
| 783 | NAME_PATH_CHECK("ALIGNMENT_INFORMATION", alignment_information, alignment_requirement);
|
|---|
| 784 | NAME_PATH_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, attrib);
|
|---|
| 785 | NAME_PATH_CHECK("ATTRIBUTE_TAG_INFORMATION", attribute_tag_information, reparse_tag);
|
|---|
| 786 |
|
|---|
| 787 | #if 0
|
|---|
| 788 | /* these are expected to differ */
|
|---|
| 789 | NAME_PATH_CHECK("ACCESS_INFORMATION", access_information, access_flags);
|
|---|
| 790 | #endif
|
|---|
| 791 |
|
|---|
| 792 | #if 0 /* unused */
|
|---|
| 793 | #define UNKNOWN_CHECK(sname, stype, tfield) do { \
|
|---|
| 794 | s1 = fnum_find(sname); \
|
|---|
| 795 | if (s1 && s1->stype.out.tfield != 0) { \
|
|---|
| 796 | printf("(%d) handle %s/%s unknown != 0 (0x%x)\n", __LINE__, \
|
|---|
| 797 | #stype, #tfield, \
|
|---|
| 798 | (uint_t)s1->stype.out.tfield); \
|
|---|
| 799 | } \
|
|---|
| 800 | s1 = fname_find(is_ipc, sname); \
|
|---|
| 801 | if (s1 && s1->stype.out.tfield != 0) { \
|
|---|
| 802 | printf("(%d) path %s/%s unknown != 0 (0x%x)\n", __LINE__, \
|
|---|
| 803 | #stype, #tfield, \
|
|---|
| 804 | (uint_t)s1->stype.out.tfield); \
|
|---|
| 805 | }} while (0)
|
|---|
| 806 | #endif
|
|---|
| 807 | /* now get a bit fancier .... */
|
|---|
| 808 |
|
|---|
| 809 | /* when we set the delete disposition then the link count should drop
|
|---|
| 810 | to 0 and delete_pending should be 1 */
|
|---|
| 811 |
|
|---|
| 812 | return ret;
|
|---|
| 813 | }
|
|---|
| 814 |
|
|---|
| 815 | /* basic testing of all RAW_FILEINFO_* calls
|
|---|
| 816 | for each call we test that it succeeds, and where possible test
|
|---|
| 817 | for consistency between the calls.
|
|---|
| 818 | */
|
|---|
| 819 | bool torture_raw_qfileinfo(struct torture_context *torture,
|
|---|
| 820 | struct smbcli_state *cli)
|
|---|
| 821 | {
|
|---|
| 822 | int fnum;
|
|---|
| 823 | bool ret;
|
|---|
| 824 | const char *fname = "\\torture_qfileinfo.txt";
|
|---|
| 825 |
|
|---|
| 826 | fnum = create_complex_file(cli, torture, fname);
|
|---|
| 827 | if (fnum == -1) {
|
|---|
| 828 | printf("ERROR: open of %s failed (%s)\n", fname, smbcli_errstr(cli->tree));
|
|---|
| 829 | return false;
|
|---|
| 830 | }
|
|---|
| 831 |
|
|---|
| 832 | ret = torture_raw_qfileinfo_internals(torture, torture, cli->tree, fnum, fname, false /* is_ipc */);
|
|---|
| 833 |
|
|---|
| 834 | smbcli_close(cli->tree, fnum);
|
|---|
| 835 | smbcli_unlink(cli->tree, fname);
|
|---|
| 836 |
|
|---|
| 837 | return ret;
|
|---|
| 838 | }
|
|---|
| 839 |
|
|---|
| 840 | bool torture_raw_qfileinfo_pipe(struct torture_context *torture,
|
|---|
| 841 | struct smbcli_state *cli)
|
|---|
| 842 | {
|
|---|
| 843 | bool ret = true;
|
|---|
| 844 | int fnum;
|
|---|
| 845 | const char *fname = "\\lsass";
|
|---|
| 846 | struct dcerpc_pipe *p;
|
|---|
| 847 | struct smbcli_tree *ipc_tree;
|
|---|
| 848 | NTSTATUS status;
|
|---|
| 849 |
|
|---|
| 850 | if (!(p = dcerpc_pipe_init(torture, cli->tree->session->transport->socket->event.ctx,
|
|---|
| 851 | lp_iconv_convenience(torture->lp_ctx)))) {
|
|---|
| 852 | return false;
|
|---|
| 853 | }
|
|---|
| 854 |
|
|---|
| 855 | status = dcerpc_pipe_open_smb(p, cli->tree, fname);
|
|---|
| 856 | torture_assert_ntstatus_ok(torture, status, "dcerpc_pipe_open_smb failed");
|
|---|
| 857 |
|
|---|
| 858 | ipc_tree = dcerpc_smb_tree(p->conn);
|
|---|
| 859 | fnum = dcerpc_smb_fnum(p->conn);
|
|---|
| 860 |
|
|---|
| 861 | ret = torture_raw_qfileinfo_internals(torture, torture, ipc_tree, fnum, fname, true /* is_ipc */);
|
|---|
| 862 |
|
|---|
| 863 | talloc_free(p);
|
|---|
| 864 | return ret;
|
|---|
| 865 | }
|
|---|