Print this page
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15069 smtorture smb2.create.blob is failed
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-1643 dtrace provider for smbsrv
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-3409 SMB2: OSX - cannot display nested folders in finder
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-3733 Want SMB2 Apple extensions
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Matt Barden <Matt.Barden@nexenta.com>
NEX-2604 Windows Explorer Stops Working / Crashes when Security Tab is accessed
NEX-2593 SMB2: unable to create folder with long filename on 4.0.3
NEX-1409 bcmp(NULL, NULL, 0) panics in DEBUG kernel
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Josef Sipek <josef.sipek@nexenta.com>
SMB-143 OS X 10.9.2 not working with SMB2
SMB-122 smbd core dumps in smbd_dc_update / smb_log
SMB-117 Win7 fails to open security properties
SMB-105 Codenomicon: SMB2 TC: 384126: Panic in smb2_query_dir with null search pattern
SMB-110 panic mapping a share from Nexentastor to the windows 2012 R2 client
SMB-109 Codenomicon: SMB TC: 409480 - Panic with SMB2_FIND request
SMB-96 Codenomicon: SMB2 TC: 141500 - Panic in smb2_decode_create_ctx
SMB-11 SMB2 message parse & dispatch
SMB-12 SMB2 Negotiate Protocol
SMB-13 SMB2 Session Setup
SMB-14 SMB2 Logoff
SMB-15 SMB2 Tree Connect
SMB-16 SMB2 Tree Disconnect
SMB-17 SMB2 Create
SMB-18 SMB2 Close
SMB-19 SMB2 Flush
SMB-20 SMB2 Read
SMB-21 SMB2 Write
SMB-22 SMB2 Lock/Unlock
SMB-23 SMB2 Ioctl
SMB-24 SMB2 Cancel
SMB-25 SMB2 Echo
SMB-26 SMB2 Query Dir
SMB-27 SMB2 Change Notify
SMB-28 SMB2 Query Info
SMB-29 SMB2 Set Info
SMB-30 SMB2 Oplocks
SMB-53 SMB2 Create Context options
(SMB2 code review cleanup 1, 2, 3)
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c
+++ new/usr/src/uts/common/fs/smbsrv/smb2_query_dir.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
|
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright 2010 Sun Microsystems, Inc. All rights reserved.
23 23 * Use is subject to license terms.
24 24 *
25 - * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
25 + * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
26 26 */
27 27
28 28 /*
29 29 * Dispatch function for SMB2_QUERY_DIRECTORY
30 30 *
31 31 * Similar to smb_trans2_find.c (from SMB1)
32 32 */
33 33
34 34 #include <smbsrv/smb2_kproto.h>
35 +#include <smbsrv/smb2_aapl.h>
35 36
36 37 /*
38 + * Internally defined info. level for MacOS support.
39 + * Make sure this does not conflict with real values in
40 + * FILE_INFORMATION_CLASS, and that it fits in 8-bits.
41 + */
42 +#define FileIdMacOsDirectoryInformation (FileMaximumInformation + 10)
43 +
44 +/*
37 45 * Args (and other state) that we carry around among the
38 46 * various functions involved in SMB2 Query Directory.
39 47 */
40 48 typedef struct smb2_find_args {
41 49 uint32_t fa_maxdata;
42 50 uint8_t fa_infoclass;
43 51 uint8_t fa_fflags;
44 52 uint16_t fa_maxcount;
45 53 uint16_t fa_eos; /* End Of Search */
46 54 uint16_t fa_fixedsize; /* size of fixed part of a returned entry */
47 55 uint32_t fa_lastkey; /* Last resume key */
48 56 int fa_last_entry; /* offset of last entry */
57 +
58 + /* Normal info, per dir. entry */
59 + smb_fileinfo_t fa_fi;
60 +
61 + /* MacOS AAPL extension stuff. */
62 + smb_macinfo_t fa_mi;
49 63 } smb2_find_args_t;
50 64
51 65 static uint32_t smb2_find_entries(smb_request_t *,
52 66 smb_odir_t *, smb2_find_args_t *);
53 -static uint32_t smb2_find_mbc_encode(smb_request_t *,
54 - smb_fileinfo_t *, smb2_find_args_t *);
67 +static uint32_t smb2_find_mbc_encode(smb_request_t *, smb2_find_args_t *);
55 68
56 69 /*
57 70 * Tunable parameter to limit the maximum
58 71 * number of entries to be returned.
59 72 */
60 73 uint16_t smb2_find_max = 128;
61 74
62 75 smb_sdrc_t
63 76 smb2_query_dir(smb_request_t *sr)
64 77 {
65 - smb2_find_args_t args;
66 - smb_odir_resume_t odir_resume;
78 + smb2_find_args_t args;
79 + smb_odir_resume_t odir_resume;
67 80 smb_ofile_t *of = NULL;
68 81 smb_odir_t *od = NULL;
69 82 char *pattern = NULL;
70 83 uint16_t StructSize;
71 84 uint32_t FileIndex;
72 85 uint16_t NameOffset;
73 86 uint16_t NameLength;
74 87 smb2fid_t smb2fid;
75 88 uint16_t sattr = SMB_SEARCH_ATTRIBUTES;
76 89 uint16_t DataOff;
77 90 uint32_t DataLen;
78 91 uint32_t status;
79 92 int skip, rc = 0;
80 93
81 94 bzero(&args, sizeof (args));
82 95 bzero(&odir_resume, sizeof (odir_resume));
83 96
84 97 /*
85 98 * SMB2 Query Directory request
86 99 */
87 100 rc = smb_mbc_decodef(
88 101 &sr->smb_data, "wbblqqwwl",
89 102 &StructSize, /* w */
90 103 &args.fa_infoclass, /* b */
91 104 &args.fa_fflags, /* b */
|
↓ open down ↓ |
15 lines elided |
↑ open up ↑ |
92 105 &FileIndex, /* l */
93 106 &smb2fid.persistent, /* q */
94 107 &smb2fid.temporal, /* q */
95 108 &NameOffset, /* w */
96 109 &NameLength, /* w */
97 110 &args.fa_maxdata); /* l */
98 111 if (rc || StructSize != 33)
99 112 return (SDRC_ERROR);
100 113
101 114 status = smb2sr_lookup_fid(sr, &smb2fid);
115 + of = sr->fid_ofile;
116 +
117 + DTRACE_SMB2_START(op__QueryDirectory, smb_request_t *, sr);
118 +
102 119 if (status)
103 120 goto errout;
104 - of = sr->fid_ofile;
105 121
106 122 /*
107 123 * If there's an input buffer (search pattern), decode it.
108 124 * Two times MAXNAMELEN because it represents the UNICODE string
109 125 * length in bytes.
110 126 */
111 127 if (NameLength >= (2 * MAXNAMELEN)) {
112 128 status = NT_STATUS_OBJECT_PATH_INVALID;
113 129 goto errout;
114 130 }
115 131 if (NameLength != 0) {
116 132 /*
117 133 * We're normally positioned at the pattern now,
118 134 * but there could be some padding before it.
119 135 */
120 136 skip = (sr->smb2_cmd_hdr + NameOffset) -
121 137 sr->smb_data.chain_offset;
122 138 if (skip < 0) {
123 139 status = NT_STATUS_OBJECT_PATH_INVALID;
124 140 goto errout;
125 141 }
126 142 if (skip > 0)
127 143 (void) smb_mbc_decodef(&sr->smb_data, "#.", skip);
128 144 rc = smb_mbc_decodef(&sr->smb_data, "%#U", sr,
129 145 NameLength, &pattern);
130 146 if (rc || pattern == NULL) {
131 147 status = NT_STATUS_OBJECT_PATH_INVALID;
132 148 goto errout;
133 149 }
134 150 } else
|
↓ open down ↓ |
20 lines elided |
↑ open up ↑ |
135 151 pattern = "*";
136 152
137 153 /*
138 154 * Setup the output buffer.
139 155 */
140 156 if (args.fa_maxdata > smb2_max_trans)
141 157 args.fa_maxdata = smb2_max_trans;
142 158 sr->raw_data.max_bytes = args.fa_maxdata;
143 159
144 160 /*
145 - * Get the mininum size of entries we will return, which
161 + * Get the fixed size of entries we will return, which
146 162 * lets us estimate the number of entries we'll need.
147 - * This should be the size with a one character name.
148 - * Compare w/ smb2_find_get_maxdata().
149 163 *
150 164 * Also use this opportunity to validate fa_infoclass.
151 165 */
152 166
153 167 switch (args.fa_infoclass) {
154 168 case FileDirectoryInformation: /* 1 */
155 169 args.fa_fixedsize = 64;
156 170 break;
157 171 case FileFullDirectoryInformation: /* 2 */
158 172 args.fa_fixedsize = 68;
159 173 break;
160 174 case FileBothDirectoryInformation: /* 3 */
161 175 args.fa_fixedsize = 94;
162 176 break;
163 177 case FileNamesInformation: /* 12 */
164 178 args.fa_fixedsize = 12;
165 179 break;
166 180 case FileIdBothDirectoryInformation: /* 37 */
|
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
167 181 args.fa_fixedsize = 96;
168 182 break;
169 183 case FileIdFullDirectoryInformation: /* 38 */
170 184 args.fa_fixedsize = 84;
171 185 break;
172 186 default:
173 187 status = NT_STATUS_INVALID_INFO_CLASS;
174 188 goto errout;
175 189 }
176 190
191 + /*
192 + * MacOS, when using the AAPL CreateContext extensions
193 + * and the "read dir attr" feature, uses a non-standard
194 + * information format for directory entries. Internally
195 + * we'll use a fake info level to represent this case.
196 + * (Wish they had just defined a new info level.)
197 + */
198 + if ((sr->session->s_flags & SMB_SSN_AAPL_READDIR) != 0 &&
199 + args.fa_infoclass == FileIdBothDirectoryInformation) {
200 + args.fa_infoclass = FileIdMacOsDirectoryInformation;
201 + args.fa_fixedsize = 96; /* yes, same size */
202 + }
203 +
177 204 args.fa_maxcount = args.fa_maxdata / (args.fa_fixedsize + 4);
178 205 if (args.fa_maxcount == 0)
179 206 args.fa_maxcount = 1;
180 207 if ((smb2_find_max != 0) && (args.fa_maxcount > smb2_find_max))
181 208 args.fa_maxcount = smb2_find_max;
182 209 if (args.fa_fflags & SMB2_QDIR_FLAG_SINGLE)
183 210 args.fa_maxcount = 1;
184 211
185 212 /*
186 213 * If this ofile does not have an odir yet, get one.
187 214 */
188 215 mutex_enter(&of->f_mutex);
189 216 if ((od = of->f_odir) == NULL) {
190 217 status = smb_odir_openfh(sr, pattern, sattr, &od);
191 218 of->f_odir = od;
192 219 }
193 220 mutex_exit(&of->f_mutex);
194 221 if (od == NULL) {
195 222 if (status == 0)
196 223 status = NT_STATUS_INTERNAL_ERROR;
197 224 goto errout;
198 225 }
199 226
200 227 /*
201 228 * "Reopen" sets a new pattern and restart.
202 229 */
203 230 if (args.fa_fflags & SMB2_QDIR_FLAG_REOPEN) {
204 231 smb_odir_reopen(od, pattern, sattr);
205 232 }
206 233
207 234 /*
208 235 * Set the correct position in the directory.
209 236 */
210 237 if (args.fa_fflags & SMB2_QDIR_FLAG_RESTART) {
211 238 odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
212 239 odir_resume.or_cookie = 0;
213 240 } else if (args.fa_fflags & SMB2_QDIR_FLAG_INDEX) {
214 241 odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
215 242 odir_resume.or_cookie = FileIndex;
216 243 } else {
217 244 odir_resume.or_type = SMB_ODIR_RESUME_CONT;
218 245 }
|
↓ open down ↓ |
32 lines elided |
↑ open up ↑ |
219 246 smb_odir_resume_at(od, &odir_resume);
220 247 of->f_seek_pos = od->d_offset;
221 248
222 249 /*
223 250 * The real work of readdir and format conversion.
224 251 */
225 252 status = smb2_find_entries(sr, od, &args);
226 253
227 254 of->f_seek_pos = od->d_offset;
228 255
229 - if (status == NT_STATUS_NO_MORE_FILES) {
230 - if (args.fa_fflags & SMB2_QDIR_FLAG_SINGLE) {
231 - status = NT_STATUS_NO_SUCH_FILE;
232 - goto errout;
233 - }
234 - /*
235 - * This is not an error, but a warning that can be
236 - * used to tell the client that this data return
237 - * is the last of the enumeration. Returning this
238 - * warning now (with the data) saves the client a
239 - * round trip that would otherwise be needed to
240 - * find out it's at the end.
241 - */
242 - sr->smb2_status = status;
243 - status = 0;
256 + if ((args.fa_fflags & SMB2_QDIR_FLAG_SINGLE) &&
257 + status == NT_STATUS_NO_MORE_FILES) {
258 + status = NT_STATUS_NO_SUCH_FILE;
244 259 }
245 - if (status)
246 - goto errout;
247 260
261 +errout:
262 + sr->smb2_status = status;
263 + DTRACE_SMB2_DONE(op__QueryDirectory, smb_request_t *, sr);
264 +
248 265 /*
266 + * Note: NT_STATUS_NO_MORE_FILES is a warning
267 + * used to tell the client that this data return
268 + * is the last of the enumeration. Returning this
269 + * warning now (with the data) saves the client a
270 + * round trip that would otherwise be needed to
271 + * find out it's at the end.
272 + */
273 + if (status != 0 &&
274 + status != NT_STATUS_NO_MORE_FILES) {
275 + smb2sr_put_error(sr, status);
276 + return (SDRC_SUCCESS);
277 + }
278 +
279 + /*
249 280 * SMB2 Query Directory reply
250 281 */
251 282 StructSize = 9;
252 283 DataOff = SMB2_HDR_SIZE + 8;
253 284 DataLen = MBC_LENGTH(&sr->raw_data);
254 285 rc = smb_mbc_encodef(
255 286 &sr->reply, "wwlC",
256 287 StructSize, /* w */
257 288 DataOff, /* w */
258 289 DataLen, /* l */
259 290 &sr->raw_data); /* C */
260 291 if (DataLen == 0)
261 292 (void) smb_mbc_encodef(&sr->reply, ".");
262 - if (rc == 0)
263 - return (SDRC_SUCCESS);
264 - status = NT_STATUS_UNSUCCESSFUL;
265 293
266 -errout:
267 - smb2sr_put_error(sr, status);
294 + if (rc)
295 + sr->smb2_status = NT_STATUS_INTERNAL_ERROR;
296 +
268 297 return (SDRC_SUCCESS);
269 298 }
270 299
271 300 /*
272 301 * smb2_find_entries
273 302 *
274 303 * Find and encode up to args->fa_maxcount directory entries.
275 304 *
276 305 * Returns:
277 306 * NT status
278 307 */
279 308 static uint32_t
280 309 smb2_find_entries(smb_request_t *sr, smb_odir_t *od, smb2_find_args_t *args)
281 310 {
282 - smb_fileinfo_t fileinfo;
283 311 smb_odir_resume_t odir_resume;
312 + char *tbuf = NULL;
313 + size_t tbuflen = 0;
284 314 uint16_t count;
285 315 uint16_t minsize;
286 316 uint32_t status = 0;
287 317 int rc = -1;
288 318
289 319 /*
290 320 * Let's stop when the remaining space will not hold a
291 321 * minimum size entry. That's the fixed part plus the
292 322 * storage size of a 1 char unicode string.
293 323 */
294 324 minsize = args->fa_fixedsize + 2;
295 325
326 + /*
327 + * FileIdMacOsDirectoryInformation needs some buffer space
328 + * for composing directory entry + stream name for lookup.
329 + * Get the buffer now to avoid alloc/free per entry.
330 + */
331 + if (args->fa_infoclass == FileIdMacOsDirectoryInformation) {
332 + tbuflen = 2 * MAXNAMELEN;
333 + tbuf = kmem_alloc(tbuflen, KM_SLEEP);
334 + }
335 +
296 336 count = 0;
297 337 while (count < args->fa_maxcount) {
298 338
299 339 if (!MBC_ROOM_FOR(&sr->raw_data, minsize)) {
300 340 status = NT_STATUS_BUFFER_OVERFLOW;
301 341 break;
302 342 }
303 343
304 - rc = smb_odir_read_fileinfo(sr, od, &fileinfo, &args->fa_eos);
344 + rc = smb_odir_read_fileinfo(sr, od,
345 + &args->fa_fi, &args->fa_eos);
305 346 if (rc == ENOENT) {
306 347 status = NT_STATUS_NO_MORE_FILES;
307 348 break;
308 349 }
309 350 if (rc != 0) {
310 351 status = smb_errno2status(rc);
311 352 break;
312 353 }
313 354 if (args->fa_eos != 0) {
314 355 /* The readdir call hit the end. */
315 356 status = NT_STATUS_NO_MORE_FILES;
316 357 break;
317 358 }
318 359
319 - status = smb2_find_mbc_encode(sr, &fileinfo, args);
360 + if (args->fa_infoclass == FileIdMacOsDirectoryInformation)
361 + (void) smb2_aapl_get_macinfo(sr, od,
362 + &args->fa_fi, &args->fa_mi, tbuf, tbuflen);
363 +
364 + if (smb2_aapl_use_file_ids == 0 &&
365 + (sr->session->s_flags & SMB_SSN_AAPL_CCEXT) != 0)
366 + args->fa_fi.fi_nodeid = 0;
367 +
368 + status = smb2_find_mbc_encode(sr, args);
320 369 if (status) {
321 370 /*
322 371 * We read a directory entry but failed to
323 372 * copy it into the output buffer. Rewind
324 373 * the directory pointer so this will be
325 374 * the first entry read next time.
326 375 */
327 376 bzero(&odir_resume, sizeof (odir_resume));
328 377 odir_resume.or_type = SMB_ODIR_RESUME_COOKIE;
329 378 odir_resume.or_cookie = args->fa_lastkey;
330 379 smb_odir_resume_at(od, &odir_resume);
331 380 break;
332 381 }
333 382
334 383 /*
335 384 * Save the offset of the next entry we'll read.
336 385 * If we fail copying, we'll need this offset.
337 386 */
338 - args->fa_lastkey = fileinfo.fi_cookie;
387 + args->fa_lastkey = args->fa_fi.fi_cookie;
339 388 ++count;
340 389 }
341 390
342 391 if (count == 0) {
343 392 ASSERT(status != 0);
344 393 } else {
345 394 /*
346 395 * We copied some directory entries, but stopped for
347 396 * NT_STATUS_NO_MORE_FILES, or something.
348 397 *
349 398 * Per [MS-FSCC] sec. 2.4, the last entry in the
350 399 * enumeration MUST have its NextEntryOffset value
351 400 * set to zero. Overwrite that in the last entry.
352 401 */
353 402 (void) smb_mbc_poke(&sr->raw_data,
354 403 args->fa_last_entry, "l", 0);
355 404 status = 0;
356 405 }
357 406
407 + if (tbuf != NULL)
408 + kmem_free(tbuf, tbuflen);
409 +
358 410 return (status);
359 411 }
360 412
361 413 /*
362 414 * smb2_mbc_encode
363 415 *
364 416 * This function encodes the mbc for one directory entry.
365 417 *
366 418 * The function returns -1 when the max data requested by client
367 419 * is reached. If the entry is valid and successful encoded, 0
368 420 * will be returned; otherwise, 1 will be returned.
369 421 *
370 422 * We always null terminate the filename. The space for the null
371 423 * is included in the maxdata calculation and is therefore included
|
↓ open down ↓ |
4 lines elided |
↑ open up ↑ |
372 424 * in the next_entry_offset. namelen is the unterminated length of
373 425 * the filename. For levels except STANDARD and EA_SIZE, if the
374 426 * filename is ascii the name length returned to the client should
375 427 * include the null terminator. Otherwise the length returned to
376 428 * the client should not include the terminator.
377 429 *
378 430 * Returns: 0 - data successfully encoded
379 431 * NT status
380 432 */
381 433 static uint32_t
382 -smb2_find_mbc_encode(smb_request_t *sr, smb_fileinfo_t *fileinfo,
383 - smb2_find_args_t *args)
434 +smb2_find_mbc_encode(smb_request_t *sr, smb2_find_args_t *args)
384 435 {
436 + smb_fileinfo_t *fileinfo = &args->fa_fi;
437 + smb_macinfo_t *macinfo = &args->fa_mi;
385 438 uint8_t buf83[26];
386 439 smb_msgbuf_t mb;
387 - int namelen, padsz;
440 + int namelen;
388 441 int shortlen = 0;
389 442 int rc, starting_offset;
390 443 uint32_t next_entry_offset;
391 444 uint32_t mb_flags = SMB_MSGBUF_UNICODE;
392 445 uint32_t resume_key;
393 446
394 447 namelen = smb_wcequiv_strlen(fileinfo->fi_name);
395 448 if (namelen == -1)
396 449 return (NT_STATUS_INTERNAL_ERROR);
397 450
398 451 /*
399 452 * Keep track of where the last entry starts so we can
400 453 * come back and poke the NextEntryOffset field. Also,
401 454 * after enumeration finishes, the caller uses this to
402 455 * poke the last entry again with zero to mark it as
403 456 * the end of the enumeration.
404 457 */
405 458 starting_offset = sr->raw_data.chain_offset;
406 459
407 460 /*
408 461 * Technically (per MS-SMB2) resume keys are optional.
409 462 * Windows doesn't need them, but MacOS does.
410 463 */
411 464 resume_key = fileinfo->fi_cookie;
412 465
413 466 /*
414 467 * This switch handles all the "information levels" (formats)
415 468 * that we support. Note that all formats have the file name
416 469 * placed after some fixed-size data, and the code to write
417 470 * the file name is factored out at the end of this switch.
418 471 */
419 472 switch (args->fa_infoclass) {
420 473
421 474 /* See also: SMB_FIND_FILE_DIRECTORY_INFO */
422 475 case FileDirectoryInformation: /* 1 */
423 476 rc = smb_mbc_encodef(
424 477 &sr->raw_data, "llTTTTqqll",
425 478 0, /* NextEntryOffset (set later) */
426 479 resume_key,
427 480 &fileinfo->fi_crtime,
428 481 &fileinfo->fi_atime,
429 482 &fileinfo->fi_mtime,
430 483 &fileinfo->fi_ctime,
431 484 fileinfo->fi_size,
432 485 fileinfo->fi_alloc_size,
433 486 fileinfo->fi_dosattr,
434 487 namelen);
435 488 break;
436 489
437 490 /* See also: SMB_FIND_FILE_FULL_DIRECTORY_INFO */
438 491 case FileFullDirectoryInformation: /* 2 */
439 492 rc = smb_mbc_encodef(
440 493 &sr->raw_data, "llTTTTqqlll",
441 494 0, /* NextEntryOffset (set later) */
442 495 resume_key,
443 496 &fileinfo->fi_crtime,
444 497 &fileinfo->fi_atime,
445 498 &fileinfo->fi_mtime,
446 499 &fileinfo->fi_ctime,
447 500 fileinfo->fi_size,
448 501 fileinfo->fi_alloc_size,
449 502 fileinfo->fi_dosattr,
450 503 namelen,
451 504 0L); /* EaSize */
452 505 break;
453 506
454 507 /* See also: SMB_FIND_FILE_ID_FULL_DIRECTORY_INFO */
455 508 case FileIdFullDirectoryInformation: /* 38 */
456 509 rc = smb_mbc_encodef(
457 510 &sr->raw_data, "llTTTTqqllllq",
458 511 0, /* NextEntryOffset (set later) */
459 512 resume_key,
460 513 &fileinfo->fi_crtime,
461 514 &fileinfo->fi_atime,
462 515 &fileinfo->fi_mtime,
463 516 &fileinfo->fi_ctime,
464 517 fileinfo->fi_size,
465 518 fileinfo->fi_alloc_size,
466 519 fileinfo->fi_dosattr,
467 520 namelen,
468 521 0L, /* EaSize */
469 522 0L, /* reserved */
470 523 fileinfo->fi_nodeid);
471 524 break;
472 525
473 526 /* See also: SMB_FIND_FILE_BOTH_DIRECTORY_INFO */
474 527 case FileBothDirectoryInformation: /* 3 */
475 528 bzero(buf83, sizeof (buf83));
476 529 smb_msgbuf_init(&mb, buf83, sizeof (buf83), mb_flags);
477 530 if (!smb_msgbuf_encode(&mb, "U", fileinfo->fi_shortname))
478 531 shortlen = smb_wcequiv_strlen(fileinfo->fi_shortname);
479 532
480 533 rc = smb_mbc_encodef(
481 534 &sr->raw_data, "llTTTTqqlllb.24c",
482 535 0, /* NextEntryOffset (set later) */
483 536 resume_key,
484 537 &fileinfo->fi_crtime,
485 538 &fileinfo->fi_atime,
486 539 &fileinfo->fi_mtime,
487 540 &fileinfo->fi_ctime,
488 541 fileinfo->fi_size,
489 542 fileinfo->fi_alloc_size,
490 543 fileinfo->fi_dosattr,
491 544 namelen,
492 545 0L, /* EaSize */
493 546 shortlen,
494 547 buf83);
495 548
496 549 smb_msgbuf_term(&mb);
497 550 break;
498 551
499 552 /* See also: SMB_FIND_FILE_ID_BOTH_DIRECTORY_INFO */
500 553 case FileIdBothDirectoryInformation: /* 37 */
501 554 bzero(buf83, sizeof (buf83));
502 555 smb_msgbuf_init(&mb, buf83, sizeof (buf83), mb_flags);
503 556 if (!smb_msgbuf_encode(&mb, "U", fileinfo->fi_shortname))
504 557 shortlen = smb_wcequiv_strlen(fileinfo->fi_shortname);
505 558
506 559 rc = smb_mbc_encodef(
507 560 &sr->raw_data, "llTTTTqqlllb.24c..q",
508 561 0, /* NextEntryOffset (set later) */
509 562 resume_key,
510 563 &fileinfo->fi_crtime,
511 564 &fileinfo->fi_atime,
512 565 &fileinfo->fi_mtime,
513 566 &fileinfo->fi_ctime,
514 567 fileinfo->fi_size, /* q */
515 568 fileinfo->fi_alloc_size, /* q */
516 569 fileinfo->fi_dosattr, /* l */
|
↓ open down ↓ |
119 lines elided |
↑ open up ↑ |
517 570 namelen, /* l */
518 571 0L, /* EaSize l */
519 572 shortlen, /* b. */
520 573 buf83, /* 24c */
521 574 /* reserved .. */
522 575 fileinfo->fi_nodeid); /* q */
523 576
524 577 smb_msgbuf_term(&mb);
525 578 break;
526 579
580 + /*
581 + * MacOS, when using the AAPL extensions (see smb2_create)
582 + * uses modified directory listing responses where the
583 + * "EA size" field is replaced with "maximum access".
584 + * This avoids the need for MacOS Finder to come back
585 + * N times to get the maximum access for every file.
586 + */
587 + case FileIdMacOsDirectoryInformation:
588 + rc = smb_mbc_encodef(
589 + &sr->raw_data, "llTTTTqqll",
590 + 0, /* NextEntryOffset (set later) */
591 + resume_key, /* a.k.a. file index */
592 + &fileinfo->fi_crtime,
593 + &fileinfo->fi_atime,
594 + &fileinfo->fi_mtime,
595 + &fileinfo->fi_ctime,
596 + fileinfo->fi_size, /* q */
597 + fileinfo->fi_alloc_size, /* q */
598 + fileinfo->fi_dosattr, /* l */
599 + namelen); /* l */
600 + if (rc != 0)
601 + break;
602 + /*
603 + * This where FileIdMacOsDirectoryInformation
604 + * differs from FileIdBothDirectoryInformation
605 + * Instead of: EaSize, ShortNameLen, ShortName;
606 + * MacOS wants: MaxAccess, ResourceForkSize, and
607 + * 16 bytes of "compressed finder info".
608 + * mi_rforksize + mi_finderinfo falls where
609 + * the 24 byte shortname would normally be.
610 + */
611 + rc = smb_mbc_encodef(
612 + &sr->raw_data, "l..q16cwq",
613 + macinfo->mi_maxaccess, /* l */
614 + /* short_name_len, reserved (..) */
615 + macinfo->mi_rforksize, /* q */
616 + macinfo->mi_finderinfo, /* 16c */
617 + macinfo->mi_unixmode, /* w */
618 + fileinfo->fi_nodeid); /* q */
619 + break;
620 +
527 621 /* See also: SMB_FIND_FILE_NAMES_INFO */
528 622 case FileNamesInformation: /* 12 */
529 623 rc = smb_mbc_encodef(
530 624 &sr->raw_data, "lll",
531 625 0, /* NextEntryOffset (set later) */
532 626 resume_key,
533 627 namelen);
534 628 break;
535 629
536 630 default:
537 631 return (NT_STATUS_INVALID_INFO_CLASS);
538 632 }
539 633 if (rc) /* smb_mbc_encodef failed */
540 634 return (NT_STATUS_BUFFER_OVERFLOW);
541 635
542 636 /*
543 637 * At this point we have written all the fixed-size data
544 638 * for the specified info. class. Now put the name and
545 639 * alignment padding, and then patch the NextEntryOffset.
|
↓ open down ↓ |
9 lines elided |
↑ open up ↑ |
546 640 * Also store this offset for the caller so they can
547 641 * patch this (again) to zero on the very last entry.
548 642 */
549 643 rc = smb_mbc_encodef(
550 644 &sr->raw_data, "U",
551 645 fileinfo->fi_name);
552 646 if (rc)
553 647 return (NT_STATUS_BUFFER_OVERFLOW);
554 648
555 649 /* Next entry needs to be 8-byte aligned. */
556 - padsz = sr->raw_data.chain_offset & 7;
557 - if (padsz) {
558 - padsz = 8 - padsz;
559 - (void) smb_mbc_encodef(&sr->raw_data, "#.", padsz);
560 - }
650 + (void) smb_mbc_put_align(&sr->raw_data, 8);
651 +
561 652 next_entry_offset = sr->raw_data.chain_offset - starting_offset;
562 653 (void) smb_mbc_poke(&sr->raw_data, starting_offset, "l",
563 654 next_entry_offset);
564 655 args->fa_last_entry = starting_offset;
565 656
566 657 return (0);
567 658 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX