2 Unix SMB/CIFS implementation.
4 NTVFS generic level mapping code
6 Copyright (C) Andrew Tridgell 2003
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
10 the Free Software Foundation; either version 2 of the License, or
11 (at your option) any later version.
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
18 You should have received a copy of the GNU General Public License
19 along with this program; if not, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 this implements mappings between info levels for NTVFS backend calls
25 the idea is that each of these functions implements one of the NTVFS
26 backend calls in terms of the 'generic' call. All backends that use
27 these functions must supply the generic call, but can if it wants to
28 also implement other levels if the need arises
30 this allows backend writers to only implement one variant of each
31 call unless they need fine grained control of the calls.
37 see if a filename ends in EXE COM DLL or SYM. This is needed for the DENY_DOS mapping for OpenX
39 static BOOL is_exe_file(const char *fname)
42 p = strrchr(fname, '.');
47 if (strcasecmp(p, "EXE") == 0 ||
48 strcasecmp(p, "COM") == 0 ||
49 strcasecmp(p, "DLL") == 0 ||
50 strcasecmp(p, "SYM") == 0) {
58 NTVFS open generic to any mapper
60 NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io)
65 if (io->generic.level == RAW_OPEN_GENERIC) {
66 return NT_STATUS_INVALID_LEVEL;
69 switch (io->generic.level) {
71 ZERO_STRUCT(io2.generic.in);
72 io2.generic.level = RAW_OPEN_GENERIC;
73 if (io->openx.in.flags & OPENX_FLAGS_REQUEST_OPLOCK) {
74 io2.generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
76 if (io->openx.in.flags & OPENX_FLAGS_REQUEST_BATCH_OPLOCK) {
77 io2.generic.in.flags |= NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
80 switch (io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) {
81 case OPENX_MODE_ACCESS_READ:
82 io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_READ;
84 case OPENX_MODE_ACCESS_WRITE:
85 io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE;
87 case OPENX_MODE_ACCESS_RDWR:
88 case OPENX_MODE_ACCESS_FCB:
89 io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
93 switch (io->openx.in.open_mode & OPENX_MODE_DENY_MASK) {
94 case OPENX_MODE_DENY_READ:
95 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
97 case OPENX_MODE_DENY_WRITE:
98 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
100 case OPENX_MODE_DENY_ALL:
101 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
103 case OPENX_MODE_DENY_NONE:
104 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
106 case OPENX_MODE_DENY_DOS:
107 /* DENY_DOS is quite strange - it depends on the filename! */
108 if (is_exe_file(io->openx.in.fname)) {
109 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
111 if ((io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) ==
112 OPENX_MODE_ACCESS_READ) {
113 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
115 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
119 case OPENX_MODE_DENY_FCB:
120 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
124 switch (io->openx.in.open_func) {
125 case (OPENX_OPEN_FUNC_FAIL):
126 io2.generic.in.open_disposition = NTCREATEX_DISP_CREATE;
128 case (OPENX_OPEN_FUNC_OPEN):
129 io2.generic.in.open_disposition = NTCREATEX_DISP_OPEN;
131 case (OPENX_OPEN_FUNC_TRUNC):
132 io2.generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
134 case (OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE):
135 io2.generic.in.open_disposition = NTCREATEX_DISP_CREATE;
137 case (OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE):
138 io2.generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
140 case (OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE):
141 io2.generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
144 io2.generic.in.alloc_size = io->openx.in.size;
145 io2.generic.in.file_attr = io->openx.in.file_attrs;
146 io2.generic.in.fname = io->openx.in.fname;
148 status = req->tcon->ntvfs_ops->open(req, &io2);
149 if (!NT_STATUS_IS_OK(status)) {
153 ZERO_STRUCT(io->openx.out);
154 io->openx.out.fnum = io2.generic.out.fnum;
155 io->openx.out.attrib = io2.generic.out.attrib;
156 io->openx.out.write_time = nt_time_to_unix(io2.generic.out.write_time);
157 io->openx.out.size = io2.generic.out.size;
163 ZERO_STRUCT(io2.generic.in);
164 io2.generic.level = RAW_OPEN_GENERIC;
165 io2.generic.in.file_attr = io->open.in.search_attrs;
166 io2.generic.in.fname = io->open.in.fname;
167 io2.generic.in.open_disposition = NTCREATEX_DISP_OPEN;
168 DEBUG(9,("ntvfs_map_open(OPEN): mapping flags=0x%x\n",
170 switch (io->open.in.flags & OPEN_FLAGS_MODE_MASK) {
171 case OPEN_FLAGS_OPEN_READ:
172 io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_READ;
173 io->open.out.rmode = DOS_OPEN_RDONLY;
175 case OPEN_FLAGS_OPEN_WRITE:
176 io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE;
177 io->open.out.rmode = DOS_OPEN_WRONLY;
179 case OPEN_FLAGS_OPEN_RDWR:
180 case 0xf: /* FCB mode */
181 io2.generic.in.access_mask = GENERIC_RIGHTS_FILE_READ |
182 GENERIC_RIGHTS_FILE_WRITE;
183 io->open.out.rmode = DOS_OPEN_RDWR; /* assume we got r/w */
186 DEBUG(2,("ntvfs_map_open(OPEN): invalid mode 0x%x\n",
187 io->open.in.flags & OPEN_FLAGS_MODE_MASK));
188 return NT_STATUS_INVALID_PARAMETER;
191 switch(io->open.in.flags & OPEN_FLAGS_DENY_MASK) {
192 case OPEN_FLAGS_DENY_DOS:
193 /* DENY_DOS is quite strange - it depends on the filename! */
194 /* REWRITE: is this necessary for OPEN? */
195 if (is_exe_file(io->open.in.fname)) {
196 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
198 if ((io->open.in.flags & OPEN_FLAGS_MODE_MASK) ==
199 OPEN_FLAGS_OPEN_READ) {
200 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
202 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
206 case OPEN_FLAGS_DENY_ALL:
207 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
209 case OPEN_FLAGS_DENY_WRITE:
210 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
212 case OPEN_FLAGS_DENY_READ:
213 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
215 case OPEN_FLAGS_DENY_NONE:
216 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE |
217 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE;
219 case 0x70: /* FCB mode */
220 io2.generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
223 DEBUG(2,("ntvfs_map_open(OPEN): invalid DENY 0x%x\n",
224 io->open.in.flags & OPEN_FLAGS_DENY_MASK));
225 return NT_STATUS_INVALID_PARAMETER;
227 DEBUG(9,("ntvfs_map_open(OPEN): mapped flags=0x%x to access_mask=0x%x and share_access=0x%x\n",
228 io->open.in.flags, io2.generic.in.access_mask, io2.generic.in.share_access));
230 status = req->tcon->ntvfs_ops->open(req, &io2);
231 if (!NT_STATUS_IS_OK(status)) {
235 ZERO_STRUCT(io->openx.out);
236 io->open.out.fnum = io2.generic.out.fnum;
237 io->open.out.attrib = io2.generic.out.attrib;
238 io->open.out.write_time = nt_time_to_unix(io2.generic.out.write_time);
239 io->open.out.size = io2.generic.out.size;
240 io->open.out.rmode = DOS_OPEN_RDWR;
245 return NT_STATUS_INVALID_LEVEL;
250 NTVFS fsinfo generic to any mapper
252 NTSTATUS ntvfs_map_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs)
255 union smb_fsinfo fs2;
257 if (fs->generic.level == RAW_QFS_GENERIC) {
258 return NT_STATUS_INVALID_LEVEL;
261 /* ask the backend for the generic info */
262 fs2.generic.level = RAW_QFS_GENERIC;
264 status = req->tcon->ntvfs_ops->fsinfo(req, &fs2);
265 if (!NT_STATUS_IS_OK(status)) {
269 /* and convert it to the required level */
270 switch (fs->generic.level) {
271 case RAW_QFS_GENERIC:
272 return NT_STATUS_INVALID_LEVEL;
274 case RAW_QFS_DSKATTR: {
275 /* map from generic to DSKATTR */
278 /* we need to scale the sizes to fit */
279 for (bpunit=64; bpunit<0x10000; bpunit *= 2) {
280 if (fs2.generic.out.blocks_total * (double)fs2.generic.out.block_size < bpunit * 512 * 65535.0) {
285 fs->dskattr.out.blocks_per_unit = bpunit;
286 fs->dskattr.out.block_size = 512;
287 fs->dskattr.out.units_total =
288 (fs2.generic.out.blocks_total * (double)fs2.generic.out.block_size) / (bpunit * 512);
289 fs->dskattr.out.units_free =
290 (fs2.generic.out.blocks_free * (double)fs2.generic.out.block_size) / (bpunit * 512);
292 /* we must return a maximum of 2G to old DOS systems, or they get very confused */
293 if (bpunit > 64 && req->smb_conn->negotiate.protocol <= PROTOCOL_LANMAN2) {
294 fs->dskattr.out.blocks_per_unit = 64;
295 fs->dskattr.out.units_total = 0xFFFF;
296 fs->dskattr.out.units_free = 0xFFFF;
301 case RAW_QFS_ALLOCATION:
302 fs->allocation.out.fs_id = fs2.generic.out.fs_id;
303 fs->allocation.out.total_alloc_units = fs2.generic.out.blocks_total;
304 fs->allocation.out.avail_alloc_units = fs2.generic.out.blocks_free;
305 fs->allocation.out.sectors_per_unit = 1;
306 fs->allocation.out.bytes_per_sector = fs2.generic.out.block_size;
310 fs->volume.out.serial_number = fs2.generic.out.serial_number;
311 fs->volume.out.volume_name.s = fs2.generic.out.volume_name;
314 case RAW_QFS_VOLUME_INFO:
315 case RAW_QFS_VOLUME_INFORMATION:
316 fs->volume_info.out.create_time = fs2.generic.out.create_time;
317 fs->volume_info.out.serial_number = fs2.generic.out.serial_number;
318 fs->volume_info.out.volume_name.s = fs2.generic.out.volume_name;
321 case RAW_QFS_SIZE_INFO:
322 case RAW_QFS_SIZE_INFORMATION:
323 fs->size_info.out.total_alloc_units = fs2.generic.out.blocks_total;
324 fs->size_info.out.avail_alloc_units = fs2.generic.out.blocks_free;
325 fs->size_info.out.sectors_per_unit = 1;
326 fs->size_info.out.bytes_per_sector = fs2.generic.out.block_size;
329 case RAW_QFS_DEVICE_INFO:
330 case RAW_QFS_DEVICE_INFORMATION:
331 fs->device_info.out.device_type = fs2.generic.out.device_type;
332 fs->device_info.out.characteristics = fs2.generic.out.device_characteristics;
335 case RAW_QFS_ATTRIBUTE_INFO:
336 case RAW_QFS_ATTRIBUTE_INFORMATION:
337 fs->attribute_info.out.fs_attr = fs2.generic.out.fs_attr;
338 fs->attribute_info.out.max_file_component_length = fs2.generic.out.max_file_component_length;
339 fs->attribute_info.out.fs_type.s = fs2.generic.out.fs_type;
342 case RAW_QFS_QUOTA_INFORMATION:
343 ZERO_STRUCT(fs->quota_information.out.unknown);
344 fs->quota_information.out.quota_soft = fs2.generic.out.quota_soft;
345 fs->quota_information.out.quota_hard = fs2.generic.out.quota_hard;
346 fs->quota_information.out.quota_flags = fs2.generic.out.quota_flags;
349 case RAW_QFS_FULL_SIZE_INFORMATION:
350 fs->full_size_information.out.total_alloc_units = fs2.generic.out.blocks_total;
351 fs->full_size_information.out.call_avail_alloc_units = fs2.generic.out.blocks_free;
352 fs->full_size_information.out.actual_avail_alloc_units = fs2.generic.out.blocks_free;
353 fs->full_size_information.out.sectors_per_unit = 1;
354 fs->full_size_information.out.bytes_per_sector = fs2.generic.out.block_size;
357 case RAW_QFS_OBJECTID_INFORMATION:
358 fs->objectid_information.out.guid = fs2.generic.out.guid;
359 ZERO_STRUCT(fs->objectid_information.out.unknown);
364 return NT_STATUS_INVALID_LEVEL;
369 NTVFS fileinfo generic to any mapper
371 NTSTATUS ntvfs_map_fileinfo(struct smbsrv_request *req, union smb_fileinfo *info, union smb_fileinfo *info2)
374 /* and convert it to the required level using results in info2 */
375 switch (info->generic.level) {
376 case RAW_FILEINFO_GENERIC:
377 return NT_STATUS_INVALID_LEVEL;
378 case RAW_FILEINFO_GETATTR:
379 info->getattr.out.attrib = info2->generic.out.attrib & 0xff;
380 info->getattr.out.size = info2->generic.out.size;
381 info->getattr.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
384 case RAW_FILEINFO_GETATTRE:
385 info->getattre.out.attrib = info2->generic.out.attrib;
386 info->getattre.out.size = info2->generic.out.size;
387 info->getattre.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
388 info->getattre.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
389 info->getattre.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
390 info->getattre.out.alloc_size = info2->generic.out.alloc_size;
393 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
394 info->network_open_information.out.create_time = info2->generic.out.create_time;
395 info->network_open_information.out.access_time = info2->generic.out.access_time;
396 info->network_open_information.out.write_time = info2->generic.out.write_time;
397 info->network_open_information.out.change_time = info2->generic.out.change_time;
398 info->network_open_information.out.alloc_size = info2->generic.out.alloc_size;
399 info->network_open_information.out.size = info2->generic.out.size;
400 info->network_open_information.out.attrib = info2->generic.out.attrib;
403 case RAW_FILEINFO_ALL_INFO:
404 case RAW_FILEINFO_ALL_INFORMATION:
405 info->all_info.out.create_time = info2->generic.out.create_time;
406 info->all_info.out.access_time = info2->generic.out.access_time;
407 info->all_info.out.write_time = info2->generic.out.write_time;
408 info->all_info.out.change_time = info2->generic.out.change_time;
409 info->all_info.out.attrib = info2->generic.out.attrib;
410 info->all_info.out.alloc_size = info2->generic.out.alloc_size;
411 info->all_info.out.size = info2->generic.out.size;
412 info->all_info.out.nlink = info2->generic.out.nlink;
413 info->all_info.out.delete_pending = info2->generic.out.delete_pending;
414 info->all_info.out.directory = info2->generic.out.directory;
415 info->all_info.out.ea_size = info2->generic.out.ea_size;
416 info->all_info.out.fname.s = info2->generic.out.fname.s;
417 info->all_info.out.fname.private_length = info2->generic.out.fname.private_length;
420 case RAW_FILEINFO_BASIC_INFO:
421 case RAW_FILEINFO_BASIC_INFORMATION:
422 info->basic_info.out.create_time = info2->generic.out.create_time;
423 info->basic_info.out.access_time = info2->generic.out.access_time;
424 info->basic_info.out.write_time = info2->generic.out.write_time;
425 info->basic_info.out.change_time = info2->generic.out.change_time;
426 info->basic_info.out.attrib = info2->generic.out.attrib;
429 case RAW_FILEINFO_STANDARD:
430 info->standard.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
431 info->standard.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
432 info->standard.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
433 info->standard.out.size = info2->generic.out.size;
434 info->standard.out.alloc_size = info2->generic.out.alloc_size;
435 info->standard.out.attrib = info2->generic.out.attrib;
438 case RAW_FILEINFO_EA_SIZE:
439 info->ea_size.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
440 info->ea_size.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
441 info->ea_size.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
442 info->ea_size.out.size = info2->generic.out.size;
443 info->ea_size.out.alloc_size = info2->generic.out.alloc_size;
444 info->ea_size.out.attrib = info2->generic.out.attrib;
445 info->ea_size.out.ea_size = info2->generic.out.ea_size;
448 case RAW_FILEINFO_STANDARD_INFO:
449 case RAW_FILEINFO_STANDARD_INFORMATION:
450 info->standard_info.out.alloc_size = info2->generic.out.alloc_size;
451 info->standard_info.out.size = info2->generic.out.size;
452 info->standard_info.out.nlink = info2->generic.out.nlink;
453 info->standard_info.out.delete_pending = info2->generic.out.delete_pending;
454 info->standard_info.out.directory = info2->generic.out.directory;
457 case RAW_FILEINFO_INTERNAL_INFORMATION:
458 info->internal_information.out.file_id = info2->generic.out.file_id;
461 case RAW_FILEINFO_EA_INFO:
462 case RAW_FILEINFO_EA_INFORMATION:
463 info->ea_info.out.ea_size = info2->generic.out.ea_size;
466 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
467 info->attribute_tag_information.out.attrib = info2->generic.out.attrib;
468 info->attribute_tag_information.out.reparse_tag = info2->generic.out.reparse_tag;
471 case RAW_FILEINFO_STREAM_INFO:
472 case RAW_FILEINFO_STREAM_INFORMATION:
473 info->stream_info.out.num_streams = info2->generic.out.num_streams;
474 if (info->stream_info.out.num_streams > 0) {
475 info->stream_info.out.streams = talloc(req->mem_ctx,
476 info->stream_info.out.num_streams * sizeof(struct stream_struct));
477 if (!info->stream_info.out.streams) {
478 DEBUG(2,("ntvfs_map_fileinfo: no memory for %d streams\n",
479 info->stream_info.out.num_streams));
480 return NT_STATUS_NO_MEMORY;
482 for (i=0; i < info->stream_info.out.num_streams; i++) {
483 info->stream_info.out.streams[i] = info2->generic.out.streams[i];
484 info->stream_info.out.streams[i].stream_name.s =
485 talloc_strdup(req->mem_ctx, info2->generic.out.streams[i].stream_name.s);
486 if (!info->stream_info.out.streams[i].stream_name.s) {
487 DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
488 return NT_STATUS_NO_MEMORY;
494 case RAW_FILEINFO_NAME_INFO:
495 case RAW_FILEINFO_NAME_INFORMATION:
496 info->name_info.out.fname.s = talloc_strdup(req->mem_ctx, info2->generic.out.fname.s);
497 info->name_info.out.fname.private_length = info2->generic.out.fname.private_length;
500 case RAW_FILEINFO_ALT_NAME_INFO:
501 case RAW_FILEINFO_ALT_NAME_INFORMATION:
502 info->alt_name_info.out.fname.s = talloc_strdup(req->mem_ctx, info2->generic.out.alt_fname.s);
503 info->alt_name_info.out.fname.private_length = info2->generic.out.alt_fname.private_length;
506 case RAW_FILEINFO_POSITION_INFORMATION:
507 info->position_information.out.position = info2->generic.out.position;
510 case RAW_FILEINFO_ALL_EAS:
511 info->all_eas.out.num_eas = info2->generic.out.num_eas;
512 if (info->all_eas.out.num_eas > 0) {
513 info->all_eas.out.eas = talloc(req->mem_ctx,
514 info->all_eas.out.num_eas * sizeof(struct ea_struct));
515 if (!info->all_eas.out.eas) {
516 DEBUG(2,("ntvfs_map_fileinfo: no memory for %d eas\n",
517 info->all_eas.out.num_eas));
518 return NT_STATUS_NO_MEMORY;
520 for (i = 0; i < info->all_eas.out.num_eas; i++) {
521 info->all_eas.out.eas[i] = info2->generic.out.eas[i];
522 info->all_eas.out.eas[i].name.s =
523 talloc_strdup(req->mem_ctx, info2->generic.out.eas[i].name.s);
524 if (!info->all_eas.out.eas[i].name.s) {
525 DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
526 return NT_STATUS_NO_MEMORY;
528 info->all_eas.out.eas[i].value.data =
529 talloc_memdup(req->mem_ctx,
530 info2->generic.out.eas[i].value.data,
531 info2->generic.out.eas[i].value.length);
532 if (!info->all_eas.out.eas[i].value.data) {
533 DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
534 return NT_STATUS_NO_MEMORY;
540 case RAW_FILEINFO_IS_NAME_VALID:
543 case RAW_FILEINFO_COMPRESSION_INFO:
544 case RAW_FILEINFO_COMPRESSION_INFORMATION:
545 info->compression_info.out.compressed_size = info2->generic.out.compressed_size;
546 info->compression_info.out.format = info2->generic.out.format;
547 info->compression_info.out.unit_shift = info2->generic.out.unit_shift;
548 info->compression_info.out.chunk_shift = info2->generic.out.chunk_shift;
549 info->compression_info.out.cluster_shift = info2->generic.out.cluster_shift;
552 case RAW_FILEINFO_ACCESS_INFORMATION:
553 info->access_information.out.access_flags = info2->generic.out.access_flags;
556 case RAW_FILEINFO_MODE_INFORMATION:
557 info->mode_information.out.mode = info2->generic.out.mode;
560 case RAW_FILEINFO_ALIGNMENT_INFORMATION:
561 info->alignment_information.out.alignment_requirement =
562 info2->generic.out.alignment_requirement;
565 case RAW_FILEINFO_UNIX_BASIC:
566 info->unix_basic_info.out.end_of_file = info2->generic.out.end_of_file;
567 info->unix_basic_info.out.num_bytes = info2->generic.out.size;
568 info->unix_basic_info.out.status_change_time = info2->generic.out.change_time;
569 info->unix_basic_info.out.access_time = info2->generic.out.access_time;
570 info->unix_basic_info.out.change_time = info2->generic.out.change_time;
571 info->unix_basic_info.out.uid = info2->generic.out.uid;
572 info->unix_basic_info.out.gid = info2->generic.out.gid;
573 info->unix_basic_info.out.file_type = info2->generic.out.file_type;
574 info->unix_basic_info.out.dev_major = info2->generic.out.device;
575 info->unix_basic_info.out.dev_minor = info2->generic.out.device;
576 info->unix_basic_info.out.unique_id = info2->generic.out.inode;
577 info->unix_basic_info.out.permissions = info2->generic.out.permissions;
578 info->unix_basic_info.out.nlink = info2->generic.out.nlink;
581 case RAW_FILEINFO_UNIX_LINK:
582 info->unix_link_info.out.link_dest = info2->generic.out.link_dest;
587 return NT_STATUS_INVALID_LEVEL;
591 NTVFS fileinfo generic to any mapper
593 NTSTATUS ntvfs_map_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info)
596 union smb_fileinfo info2;
598 if (info->generic.level == RAW_FILEINFO_GENERIC) {
599 return NT_STATUS_INVALID_LEVEL;
602 /* ask the backend for the generic info */
603 info2.generic.level = RAW_FILEINFO_GENERIC;
604 info2.generic.in.fnum = info->generic.in.fnum;
606 status = req->tcon->ntvfs_ops->qfileinfo(req, &info2);
607 if (!NT_STATUS_IS_OK(status)) {
610 return ntvfs_map_fileinfo(req, info, &info2);
614 NTVFS pathinfo generic to any mapper
616 NTSTATUS ntvfs_map_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info)
619 union smb_fileinfo info2;
621 if (info->generic.level == RAW_FILEINFO_GENERIC) {
622 return NT_STATUS_INVALID_LEVEL;
625 /* ask the backend for the generic info */
626 info2.generic.level = RAW_FILEINFO_GENERIC;
627 info2.generic.in.fname = info->generic.in.fname;
629 status = req->tcon->ntvfs_ops->qpathinfo(req, &info2);
630 if (!NT_STATUS_IS_OK(status)) {
633 return ntvfs_map_fileinfo(req, info, &info2);