2 Unix SMB/CIFS implementation.
4 NTVFS generic level mapping code
6 Copyright (C) Andrew Tridgell 2003-2004
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
38 DENY_DOS mapping for OpenX
40 static BOOL is_exe_file(const char *fname)
43 p = strrchr(fname, '.');
48 if (strcasecmp(p, "EXE") == 0 ||
49 strcasecmp(p, "COM") == 0 ||
50 strcasecmp(p, "DLL") == 0 ||
51 strcasecmp(p, "SYM") == 0) {
59 NTVFS open generic to any mapper
61 NTSTATUS ntvfs_map_open(struct smbsrv_request *req, union smb_open *io,
62 struct ntvfs_module_context *ntvfs)
67 io2 = talloc_p(req, union smb_open);
69 return NT_STATUS_NO_MEMORY;
72 /* must be synchronous, or we won't be called to do the
74 req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
76 switch (io->generic.level) {
77 case RAW_OPEN_GENERIC:
78 return NT_STATUS_INVALID_LEVEL;
81 ZERO_STRUCT(io2->generic.in);
82 io2->generic.level = RAW_OPEN_GENERIC;
83 if (io->openx.in.flags & OPENX_FLAGS_REQUEST_OPLOCK) {
84 io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_OPLOCK;
86 if (io->openx.in.flags & OPENX_FLAGS_REQUEST_BATCH_OPLOCK) {
87 io2->generic.in.flags |= NTCREATEX_FLAGS_REQUEST_BATCH_OPLOCK;
90 switch (io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) {
91 case OPENX_MODE_ACCESS_READ:
92 io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ;
94 case OPENX_MODE_ACCESS_WRITE:
95 io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE;
97 case OPENX_MODE_ACCESS_RDWR:
98 case OPENX_MODE_ACCESS_FCB:
99 io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_ALL_ACCESS;
103 switch (io->openx.in.open_mode & OPENX_MODE_DENY_MASK) {
104 case OPENX_MODE_DENY_READ:
105 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
107 case OPENX_MODE_DENY_WRITE:
108 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
110 case OPENX_MODE_DENY_ALL:
111 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
113 case OPENX_MODE_DENY_NONE:
114 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
116 case OPENX_MODE_DENY_DOS:
117 /* DENY_DOS is quite strange - it depends on the filename! */
118 if (is_exe_file(io->openx.in.fname)) {
119 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
121 if ((io->openx.in.open_mode & OPENX_MODE_ACCESS_MASK) ==
122 OPENX_MODE_ACCESS_READ) {
123 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
125 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
129 case OPENX_MODE_DENY_FCB:
130 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
134 switch (io->openx.in.open_func) {
135 case (OPENX_OPEN_FUNC_FAIL):
136 io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
138 case (OPENX_OPEN_FUNC_OPEN):
139 io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN;
141 case (OPENX_OPEN_FUNC_TRUNC):
142 io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE;
144 case (OPENX_OPEN_FUNC_FAIL | OPENX_OPEN_FUNC_CREATE):
145 io2->generic.in.open_disposition = NTCREATEX_DISP_CREATE;
147 case (OPENX_OPEN_FUNC_OPEN | OPENX_OPEN_FUNC_CREATE):
148 io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN_IF;
150 case (OPENX_OPEN_FUNC_TRUNC | OPENX_OPEN_FUNC_CREATE):
151 io2->generic.in.open_disposition = NTCREATEX_DISP_OVERWRITE_IF;
154 io2->generic.in.alloc_size = io->openx.in.size;
155 io2->generic.in.file_attr = io->openx.in.file_attrs;
156 io2->generic.in.fname = io->openx.in.fname;
158 status = ntvfs->ops->open(ntvfs, req, io2);
159 if (!NT_STATUS_IS_OK(status)) {
163 ZERO_STRUCT(io->openx.out);
164 io->openx.out.fnum = io2->generic.out.fnum;
165 io->openx.out.attrib = io2->generic.out.attrib;
166 io->openx.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
167 io->openx.out.size = io2->generic.out.size;
173 ZERO_STRUCT(io2->generic.in);
174 io2->generic.level = RAW_OPEN_GENERIC;
175 io2->generic.in.file_attr = io->open.in.search_attrs;
176 io2->generic.in.fname = io->open.in.fname;
177 io2->generic.in.open_disposition = NTCREATEX_DISP_OPEN;
178 DEBUG(9,("ntvfs_map_open(OPEN): mapping flags=0x%x\n",
180 switch (io->open.in.flags & OPEN_FLAGS_MODE_MASK) {
181 case OPEN_FLAGS_OPEN_READ:
182 io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ;
183 io->open.out.rmode = DOS_OPEN_RDONLY;
185 case OPEN_FLAGS_OPEN_WRITE:
186 io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_WRITE;
187 io->open.out.rmode = DOS_OPEN_WRONLY;
189 case OPEN_FLAGS_OPEN_RDWR:
190 case 0xf: /* FCB mode */
191 io2->generic.in.access_mask = GENERIC_RIGHTS_FILE_READ |
192 GENERIC_RIGHTS_FILE_WRITE;
193 io->open.out.rmode = DOS_OPEN_RDWR; /* assume we got r/w */
196 DEBUG(2,("ntvfs_map_open(OPEN): invalid mode 0x%x\n",
197 io->open.in.flags & OPEN_FLAGS_MODE_MASK));
198 return NT_STATUS_INVALID_PARAMETER;
201 switch(io->open.in.flags & OPEN_FLAGS_DENY_MASK) {
202 case OPEN_FLAGS_DENY_DOS:
203 /* DENY_DOS is quite strange - it depends on the filename! */
204 /* REWRITE: is this necessary for OPEN? */
205 if (is_exe_file(io->open.in.fname)) {
206 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_WRITE;
208 if ((io->open.in.flags & OPEN_FLAGS_MODE_MASK) ==
209 OPEN_FLAGS_OPEN_READ) {
210 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
212 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
216 case OPEN_FLAGS_DENY_ALL:
217 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
219 case OPEN_FLAGS_DENY_WRITE:
220 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_READ;
222 case OPEN_FLAGS_DENY_READ:
223 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE;
225 case OPEN_FLAGS_DENY_NONE:
226 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_WRITE |
227 NTCREATEX_SHARE_ACCESS_READ | NTCREATEX_SHARE_ACCESS_DELETE;
229 case 0x70: /* FCB mode */
230 io2->generic.in.share_access = NTCREATEX_SHARE_ACCESS_NONE;
233 DEBUG(2,("ntvfs_map_open(OPEN): invalid DENY 0x%x\n",
234 io->open.in.flags & OPEN_FLAGS_DENY_MASK));
235 return NT_STATUS_INVALID_PARAMETER;
237 DEBUG(9,("ntvfs_map_open(OPEN): mapped flags=0x%x to access_mask=0x%x and share_access=0x%x\n",
238 io->open.in.flags, io2->generic.in.access_mask, io2->generic.in.share_access));
240 status = ntvfs->ops->open(ntvfs, req, io2);
241 if (!NT_STATUS_IS_OK(status)) {
245 ZERO_STRUCT(io->openx.out);
246 io->open.out.fnum = io2->generic.out.fnum;
247 io->open.out.attrib = io2->generic.out.attrib;
248 io->open.out.write_time = nt_time_to_unix(io2->generic.out.write_time);
249 io->open.out.size = io2->generic.out.size;
250 io->open.out.rmode = DOS_OPEN_RDWR;
255 return NT_STATUS_INVALID_LEVEL;
260 NTVFS fsinfo generic to any mapper
262 NTSTATUS ntvfs_map_fsinfo(struct smbsrv_request *req, union smb_fsinfo *fs,
263 struct ntvfs_module_context *ntvfs)
266 union smb_fsinfo *fs2;
268 fs2 = talloc_p(req, union smb_fsinfo);
270 return NT_STATUS_NO_MEMORY;
273 if (fs->generic.level == RAW_QFS_GENERIC) {
274 return NT_STATUS_INVALID_LEVEL;
277 /* ask the backend for the generic info */
278 fs2->generic.level = RAW_QFS_GENERIC;
280 status = ntvfs->ops->fsinfo(ntvfs, req, fs2);
281 if (!NT_STATUS_IS_OK(status)) {
285 /* and convert it to the required level */
286 switch (fs->generic.level) {
287 case RAW_QFS_GENERIC:
288 return NT_STATUS_INVALID_LEVEL;
290 case RAW_QFS_DSKATTR: {
291 /* map from generic to DSKATTR */
294 /* we need to scale the sizes to fit */
295 for (bpunit=64; bpunit<0x10000; bpunit *= 2) {
296 if (fs2->generic.out.blocks_total * (double)fs2->generic.out.block_size < bpunit * 512 * 65535.0) {
301 fs->dskattr.out.blocks_per_unit = bpunit;
302 fs->dskattr.out.block_size = 512;
303 fs->dskattr.out.units_total =
304 (fs2->generic.out.blocks_total * (double)fs2->generic.out.block_size) / (bpunit * 512);
305 fs->dskattr.out.units_free =
306 (fs2->generic.out.blocks_free * (double)fs2->generic.out.block_size) / (bpunit * 512);
308 /* we must return a maximum of 2G to old DOS systems, or they get very confused */
309 if (bpunit > 64 && req->smb_conn->negotiate.protocol <= PROTOCOL_LANMAN2) {
310 fs->dskattr.out.blocks_per_unit = 64;
311 fs->dskattr.out.units_total = 0xFFFF;
312 fs->dskattr.out.units_free = 0xFFFF;
317 case RAW_QFS_ALLOCATION:
318 fs->allocation.out.fs_id = fs2->generic.out.fs_id;
319 fs->allocation.out.total_alloc_units = fs2->generic.out.blocks_total;
320 fs->allocation.out.avail_alloc_units = fs2->generic.out.blocks_free;
321 fs->allocation.out.sectors_per_unit = 1;
322 fs->allocation.out.bytes_per_sector = fs2->generic.out.block_size;
326 fs->volume.out.serial_number = fs2->generic.out.serial_number;
327 fs->volume.out.volume_name.s = fs2->generic.out.volume_name;
330 case RAW_QFS_VOLUME_INFO:
331 case RAW_QFS_VOLUME_INFORMATION:
332 fs->volume_info.out.create_time = fs2->generic.out.create_time;
333 fs->volume_info.out.serial_number = fs2->generic.out.serial_number;
334 fs->volume_info.out.volume_name.s = fs2->generic.out.volume_name;
337 case RAW_QFS_SIZE_INFO:
338 case RAW_QFS_SIZE_INFORMATION:
339 fs->size_info.out.total_alloc_units = fs2->generic.out.blocks_total;
340 fs->size_info.out.avail_alloc_units = fs2->generic.out.blocks_free;
341 fs->size_info.out.sectors_per_unit = 1;
342 fs->size_info.out.bytes_per_sector = fs2->generic.out.block_size;
345 case RAW_QFS_DEVICE_INFO:
346 case RAW_QFS_DEVICE_INFORMATION:
347 fs->device_info.out.device_type = fs2->generic.out.device_type;
348 fs->device_info.out.characteristics = fs2->generic.out.device_characteristics;
351 case RAW_QFS_ATTRIBUTE_INFO:
352 case RAW_QFS_ATTRIBUTE_INFORMATION:
353 fs->attribute_info.out.fs_attr = fs2->generic.out.fs_attr;
354 fs->attribute_info.out.max_file_component_length = fs2->generic.out.max_file_component_length;
355 fs->attribute_info.out.fs_type.s = fs2->generic.out.fs_type;
358 case RAW_QFS_QUOTA_INFORMATION:
359 ZERO_STRUCT(fs->quota_information.out.unknown);
360 fs->quota_information.out.quota_soft = fs2->generic.out.quota_soft;
361 fs->quota_information.out.quota_hard = fs2->generic.out.quota_hard;
362 fs->quota_information.out.quota_flags = fs2->generic.out.quota_flags;
365 case RAW_QFS_FULL_SIZE_INFORMATION:
366 fs->full_size_information.out.total_alloc_units = fs2->generic.out.blocks_total;
367 fs->full_size_information.out.call_avail_alloc_units = fs2->generic.out.blocks_free;
368 fs->full_size_information.out.actual_avail_alloc_units = fs2->generic.out.blocks_free;
369 fs->full_size_information.out.sectors_per_unit = 1;
370 fs->full_size_information.out.bytes_per_sector = fs2->generic.out.block_size;
373 case RAW_QFS_OBJECTID_INFORMATION:
374 fs->objectid_information.out.guid = fs2->generic.out.guid;
375 ZERO_STRUCT(fs->objectid_information.out.unknown);
380 return NT_STATUS_INVALID_LEVEL;
385 NTVFS fileinfo generic to any mapper
387 NTSTATUS ntvfs_map_fileinfo(struct smbsrv_request *req, union smb_fileinfo *info,
388 union smb_fileinfo *info2)
391 /* and convert it to the required level using results in info2 */
392 switch (info->generic.level) {
393 case RAW_FILEINFO_GENERIC:
394 return NT_STATUS_INVALID_LEVEL;
395 case RAW_FILEINFO_GETATTR:
396 info->getattr.out.attrib = info2->generic.out.attrib & 0xff;
397 info->getattr.out.size = info2->generic.out.size;
398 info->getattr.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
401 case RAW_FILEINFO_GETATTRE:
402 info->getattre.out.attrib = info2->generic.out.attrib;
403 info->getattre.out.size = info2->generic.out.size;
404 info->getattre.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
405 info->getattre.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
406 info->getattre.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
407 info->getattre.out.alloc_size = info2->generic.out.alloc_size;
410 case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
411 info->network_open_information.out.create_time = info2->generic.out.create_time;
412 info->network_open_information.out.access_time = info2->generic.out.access_time;
413 info->network_open_information.out.write_time = info2->generic.out.write_time;
414 info->network_open_information.out.change_time = info2->generic.out.change_time;
415 info->network_open_information.out.alloc_size = info2->generic.out.alloc_size;
416 info->network_open_information.out.size = info2->generic.out.size;
417 info->network_open_information.out.attrib = info2->generic.out.attrib;
420 case RAW_FILEINFO_ALL_INFO:
421 case RAW_FILEINFO_ALL_INFORMATION:
422 info->all_info.out.create_time = info2->generic.out.create_time;
423 info->all_info.out.access_time = info2->generic.out.access_time;
424 info->all_info.out.write_time = info2->generic.out.write_time;
425 info->all_info.out.change_time = info2->generic.out.change_time;
426 info->all_info.out.attrib = info2->generic.out.attrib;
427 info->all_info.out.alloc_size = info2->generic.out.alloc_size;
428 info->all_info.out.size = info2->generic.out.size;
429 info->all_info.out.nlink = info2->generic.out.nlink;
430 info->all_info.out.delete_pending = info2->generic.out.delete_pending;
431 info->all_info.out.directory = info2->generic.out.directory;
432 info->all_info.out.ea_size = info2->generic.out.ea_size;
433 info->all_info.out.fname.s = info2->generic.out.fname.s;
434 info->all_info.out.fname.private_length = info2->generic.out.fname.private_length;
437 case RAW_FILEINFO_BASIC_INFO:
438 case RAW_FILEINFO_BASIC_INFORMATION:
439 info->basic_info.out.create_time = info2->generic.out.create_time;
440 info->basic_info.out.access_time = info2->generic.out.access_time;
441 info->basic_info.out.write_time = info2->generic.out.write_time;
442 info->basic_info.out.change_time = info2->generic.out.change_time;
443 info->basic_info.out.attrib = info2->generic.out.attrib;
446 case RAW_FILEINFO_STANDARD:
447 info->standard.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
448 info->standard.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
449 info->standard.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
450 info->standard.out.size = info2->generic.out.size;
451 info->standard.out.alloc_size = info2->generic.out.alloc_size;
452 info->standard.out.attrib = info2->generic.out.attrib;
455 case RAW_FILEINFO_EA_SIZE:
456 info->ea_size.out.create_time = nt_time_to_unix(info2->generic.out.create_time);
457 info->ea_size.out.access_time = nt_time_to_unix(info2->generic.out.access_time);
458 info->ea_size.out.write_time = nt_time_to_unix(info2->generic.out.write_time);
459 info->ea_size.out.size = info2->generic.out.size;
460 info->ea_size.out.alloc_size = info2->generic.out.alloc_size;
461 info->ea_size.out.attrib = info2->generic.out.attrib;
462 info->ea_size.out.ea_size = info2->generic.out.ea_size;
465 case RAW_FILEINFO_STANDARD_INFO:
466 case RAW_FILEINFO_STANDARD_INFORMATION:
467 info->standard_info.out.alloc_size = info2->generic.out.alloc_size;
468 info->standard_info.out.size = info2->generic.out.size;
469 info->standard_info.out.nlink = info2->generic.out.nlink;
470 info->standard_info.out.delete_pending = info2->generic.out.delete_pending;
471 info->standard_info.out.directory = info2->generic.out.directory;
474 case RAW_FILEINFO_INTERNAL_INFORMATION:
475 info->internal_information.out.file_id = info2->generic.out.file_id;
478 case RAW_FILEINFO_EA_INFO:
479 case RAW_FILEINFO_EA_INFORMATION:
480 info->ea_info.out.ea_size = info2->generic.out.ea_size;
483 case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
484 info->attribute_tag_information.out.attrib = info2->generic.out.attrib;
485 info->attribute_tag_information.out.reparse_tag = info2->generic.out.reparse_tag;
488 case RAW_FILEINFO_STREAM_INFO:
489 case RAW_FILEINFO_STREAM_INFORMATION:
490 info->stream_info.out.num_streams = info2->generic.out.num_streams;
491 if (info->stream_info.out.num_streams > 0) {
492 info->stream_info.out.streams = talloc(req,
493 info->stream_info.out.num_streams * sizeof(struct stream_struct));
494 if (!info->stream_info.out.streams) {
495 DEBUG(2,("ntvfs_map_fileinfo: no memory for %d streams\n",
496 info->stream_info.out.num_streams));
497 return NT_STATUS_NO_MEMORY;
499 for (i=0; i < info->stream_info.out.num_streams; i++) {
500 info->stream_info.out.streams[i] = info2->generic.out.streams[i];
501 info->stream_info.out.streams[i].stream_name.s =
502 talloc_strdup(req, info2->generic.out.streams[i].stream_name.s);
503 if (!info->stream_info.out.streams[i].stream_name.s) {
504 DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
505 return NT_STATUS_NO_MEMORY;
511 case RAW_FILEINFO_NAME_INFO:
512 case RAW_FILEINFO_NAME_INFORMATION:
513 info->name_info.out.fname.s = talloc_strdup(req, info2->generic.out.fname.s);
514 info->name_info.out.fname.private_length = info2->generic.out.fname.private_length;
517 case RAW_FILEINFO_ALT_NAME_INFO:
518 case RAW_FILEINFO_ALT_NAME_INFORMATION:
519 info->alt_name_info.out.fname.s = talloc_strdup(req, info2->generic.out.alt_fname.s);
520 info->alt_name_info.out.fname.private_length = info2->generic.out.alt_fname.private_length;
523 case RAW_FILEINFO_POSITION_INFORMATION:
524 info->position_information.out.position = info2->generic.out.position;
527 case RAW_FILEINFO_ALL_EAS:
528 info->all_eas.out.num_eas = info2->generic.out.num_eas;
529 if (info->all_eas.out.num_eas > 0) {
530 info->all_eas.out.eas = talloc(req,
531 info->all_eas.out.num_eas * sizeof(struct ea_struct));
532 if (!info->all_eas.out.eas) {
533 DEBUG(2,("ntvfs_map_fileinfo: no memory for %d eas\n",
534 info->all_eas.out.num_eas));
535 return NT_STATUS_NO_MEMORY;
537 for (i = 0; i < info->all_eas.out.num_eas; i++) {
538 info->all_eas.out.eas[i] = info2->generic.out.eas[i];
539 info->all_eas.out.eas[i].name.s =
540 talloc_strdup(req, info2->generic.out.eas[i].name.s);
541 if (!info->all_eas.out.eas[i].name.s) {
542 DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
543 return NT_STATUS_NO_MEMORY;
545 info->all_eas.out.eas[i].value.data =
547 info2->generic.out.eas[i].value.data,
548 info2->generic.out.eas[i].value.length);
549 if (!info->all_eas.out.eas[i].value.data) {
550 DEBUG(2,("ntvfs_map_fileinfo: no memory for stream_name\n"));
551 return NT_STATUS_NO_MEMORY;
557 case RAW_FILEINFO_IS_NAME_VALID:
560 case RAW_FILEINFO_COMPRESSION_INFO:
561 case RAW_FILEINFO_COMPRESSION_INFORMATION:
562 info->compression_info.out.compressed_size = info2->generic.out.compressed_size;
563 info->compression_info.out.format = info2->generic.out.format;
564 info->compression_info.out.unit_shift = info2->generic.out.unit_shift;
565 info->compression_info.out.chunk_shift = info2->generic.out.chunk_shift;
566 info->compression_info.out.cluster_shift = info2->generic.out.cluster_shift;
569 case RAW_FILEINFO_ACCESS_INFORMATION:
570 info->access_information.out.access_flags = info2->generic.out.access_flags;
573 case RAW_FILEINFO_MODE_INFORMATION:
574 info->mode_information.out.mode = info2->generic.out.mode;
577 case RAW_FILEINFO_ALIGNMENT_INFORMATION:
578 info->alignment_information.out.alignment_requirement =
579 info2->generic.out.alignment_requirement;
582 case RAW_FILEINFO_UNIX_BASIC:
583 info->unix_basic_info.out.end_of_file = info2->generic.out.end_of_file;
584 info->unix_basic_info.out.num_bytes = info2->generic.out.size;
585 info->unix_basic_info.out.status_change_time = info2->generic.out.change_time;
586 info->unix_basic_info.out.access_time = info2->generic.out.access_time;
587 info->unix_basic_info.out.change_time = info2->generic.out.change_time;
588 info->unix_basic_info.out.uid = info2->generic.out.uid;
589 info->unix_basic_info.out.gid = info2->generic.out.gid;
590 info->unix_basic_info.out.file_type = info2->generic.out.file_type;
591 info->unix_basic_info.out.dev_major = info2->generic.out.device;
592 info->unix_basic_info.out.dev_minor = info2->generic.out.device;
593 info->unix_basic_info.out.unique_id = info2->generic.out.inode;
594 info->unix_basic_info.out.permissions = info2->generic.out.permissions;
595 info->unix_basic_info.out.nlink = info2->generic.out.nlink;
598 case RAW_FILEINFO_UNIX_LINK:
599 info->unix_link_info.out.link_dest = info2->generic.out.link_dest;
604 return NT_STATUS_INVALID_LEVEL;
608 NTVFS fileinfo generic to any mapper
610 NTSTATUS ntvfs_map_qfileinfo(struct smbsrv_request *req, union smb_fileinfo *info,
611 struct ntvfs_module_context *ntvfs)
614 union smb_fileinfo *info2;
616 info2 = talloc_p(req, union smb_fileinfo);
618 return NT_STATUS_NO_MEMORY;
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.fnum = info->generic.in.fnum;
629 status = ntvfs->ops->qfileinfo(ntvfs, req, info2);
630 if (!NT_STATUS_IS_OK(status)) {
633 return ntvfs_map_fileinfo(req, info, info2);
637 NTVFS pathinfo generic to any mapper
639 NTSTATUS ntvfs_map_qpathinfo(struct smbsrv_request *req, union smb_fileinfo *info,
640 struct ntvfs_module_context *ntvfs)
643 union smb_fileinfo *info2;
645 info2 = talloc_p(req, union smb_fileinfo);
647 return NT_STATUS_NO_MEMORY;
650 if (info->generic.level == RAW_FILEINFO_GENERIC) {
651 return NT_STATUS_INVALID_LEVEL;
654 /* ask the backend for the generic info */
655 info2->generic.level = RAW_FILEINFO_GENERIC;
656 info2->generic.in.fname = info->generic.in.fname;
658 /* must be synchronous, or we won't be called to do the
660 req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
662 status = ntvfs->ops->qpathinfo(ntvfs, req, info2);
663 if (!NT_STATUS_IS_OK(status)) {
666 return ntvfs_map_fileinfo(req, info, info2);
671 NTVFS lock generic to any mapper
673 NTSTATUS ntvfs_map_lock(struct smbsrv_request *req, union smb_lock *lck,
674 struct ntvfs_module_context *ntvfs)
676 union smb_lock *lck2;
677 struct smb_lock_entry *locks;
679 lck2 = talloc_p(req, union smb_lock);
681 return NT_STATUS_NO_MEMORY;
684 locks = talloc_array_p(lck2, struct smb_lock_entry, 1);
686 return NT_STATUS_NO_MEMORY;
689 switch (lck->generic.level) {
691 return NT_STATUS_INVALID_LEVEL;
694 lck2->generic.in.ulock_cnt = 0;
695 lck2->generic.in.lock_cnt = 1;
698 case RAW_LOCK_UNLOCK:
699 lck2->generic.in.ulock_cnt = 1;
700 lck2->generic.in.lock_cnt = 0;
704 lck2->generic.level = RAW_LOCK_GENERIC;
705 lck2->generic.in.fnum = lck->lock.in.fnum;
706 lck2->generic.in.mode = 0;
707 lck2->generic.in.timeout = 0;
708 lck2->generic.in.locks = locks;
709 locks->pid = req->smbpid;
710 locks->offset = lck->lock.in.offset;
711 locks->count = lck->lock.in.count;
713 return ntvfs->ops->lock(ntvfs, req, lck2);
718 NTVFS write generic to any mapper
720 NTSTATUS ntvfs_map_write(struct smbsrv_request *req, union smb_write *wr,
721 struct ntvfs_module_context *ntvfs)
723 union smb_write *wr2;
728 wr2 = talloc_p(req, union smb_write);
730 return NT_STATUS_NO_MEMORY;
733 wr2->generic.level = RAW_WRITE_GENERIC;
735 /* we can't map asynchronously */
736 req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
738 switch (wr->generic.level) {
739 case RAW_WRITE_WRITEX:
740 status = NT_STATUS_INVALID_LEVEL;
743 case RAW_WRITE_WRITE:
744 wr2->generic.in.fnum = wr->write.in.fnum;
745 wr2->generic.in.offset = wr->write.in.offset;
746 wr2->generic.in.wmode = 0;
747 wr2->generic.in.remaining = wr->write.in.remaining;
748 wr2->generic.in.count = wr->write.in.count;
749 wr2->generic.in.data = wr->write.in.data;
750 status = ntvfs->ops->write(ntvfs, req, wr2);
751 wr->write.out.nwritten = wr2->generic.out.nwritten;
754 case RAW_WRITE_WRITEUNLOCK:
755 lck = talloc_p(wr2, union smb_lock);
757 return NT_STATUS_NO_MEMORY;
760 wr2->generic.in.fnum = wr->writeunlock.in.fnum;
761 wr2->generic.in.offset = wr->writeunlock.in.offset;
762 wr2->generic.in.wmode = 0;
763 wr2->generic.in.remaining = wr->writeunlock.in.remaining;
764 wr2->generic.in.count = wr->writeunlock.in.count;
765 wr2->generic.in.data = wr->writeunlock.in.data;
767 lck->unlock.level = RAW_LOCK_UNLOCK;
768 lck->unlock.in.fnum = wr->writeunlock.in.fnum;
769 lck->unlock.in.count = wr->writeunlock.in.count;
770 lck->unlock.in.offset = wr->writeunlock.in.offset;
772 status = ntvfs->ops->write(ntvfs, req, wr2);
774 wr->writeunlock.out.nwritten = wr2->generic.out.nwritten;
776 if (NT_STATUS_IS_OK(status) &&
777 lck->unlock.in.count != 0) {
778 status = ntvfs->ops->lock(ntvfs, req, lck);
782 case RAW_WRITE_WRITECLOSE:
783 cl = talloc_p(wr2, union smb_close);
785 return NT_STATUS_NO_MEMORY;
788 wr2->generic.in.fnum = wr->writeclose.in.fnum;
789 wr2->generic.in.offset = wr->writeclose.in.offset;
790 wr2->generic.in.wmode = 0;
791 wr2->generic.in.remaining = 0;
792 wr2->generic.in.count = wr->writeclose.in.count;
793 wr2->generic.in.data = wr->writeclose.in.data;
795 cl->close.level = RAW_CLOSE_CLOSE;
796 cl->close.in.fnum = wr->writeclose.in.fnum;
797 cl->close.in.write_time = wr->writeclose.in.mtime;
799 status = ntvfs->ops->write(ntvfs, req, wr2);
800 wr->writeclose.out.nwritten = wr2->generic.out.nwritten;
802 if (NT_STATUS_IS_OK(status) &&
803 wr2->generic.in.count != 0) {
804 status = ntvfs->ops->close(ntvfs, req, cl);
808 case RAW_WRITE_SPLWRITE:
809 wr2->generic.in.fnum = wr->splwrite.in.fnum;
810 wr2->generic.in.offset = 0;
811 wr2->generic.in.wmode = 0;
812 wr2->generic.in.remaining = 0;
813 wr2->generic.in.count = wr->splwrite.in.count;
814 wr2->generic.in.data = wr->splwrite.in.data;
815 status = ntvfs->ops->write(ntvfs, req, wr2);
825 NTVFS read generic to any mapper
827 NTSTATUS ntvfs_map_read(struct smbsrv_request *req, union smb_read *rd,
828 struct ntvfs_module_context *ntvfs)
834 rd2 = talloc_p(req, union smb_read);
836 return NT_STATUS_NO_MEMORY;
839 rd2->generic.level = RAW_READ_GENERIC;
841 /* we can't map asynchronously */
842 req->control_flags &= ~REQ_CONTROL_MAY_ASYNC;
844 switch (rd->generic.level) {
846 status = NT_STATUS_INVALID_LEVEL;
850 rd2->generic.in.fnum = rd->read.in.fnum;
851 rd2->generic.in.offset = rd->read.in.offset;
852 rd2->generic.in.mincnt = rd->read.in.count;
853 rd2->generic.in.maxcnt = rd->read.in.count;
854 rd2->generic.in.remaining = rd->read.in.remaining;
855 rd2->generic.out.data = rd->read.out.data;
856 status = ntvfs->ops->read(ntvfs, req, rd2);
857 rd->read.out.nread = rd2->generic.out.nread;
860 case RAW_READ_READBRAW:
861 rd2->generic.in.fnum = rd->readbraw.in.fnum;
862 rd2->generic.in.offset = rd->readbraw.in.offset;
863 rd2->generic.in.mincnt = rd->readbraw.in.mincnt;
864 rd2->generic.in.maxcnt = rd->readbraw.in.maxcnt;
865 rd2->generic.in.remaining = 0;
866 rd2->generic.out.data = rd->readbraw.out.data;
867 status = ntvfs->ops->read(ntvfs, req, rd2);
868 rd->readbraw.out.nread = rd2->generic.out.nread;
871 case RAW_READ_LOCKREAD:
872 lck = talloc_p(rd2, union smb_lock);
874 return NT_STATUS_NO_MEMORY;
877 rd2->generic.in.fnum = rd->lockread.in.fnum;
878 rd2->generic.in.offset = rd->lockread.in.offset;
879 rd2->generic.in.mincnt = rd->lockread.in.count;
880 rd2->generic.in.maxcnt = rd->lockread.in.count;
881 rd2->generic.in.remaining = rd->lockread.in.remaining;
882 rd2->generic.out.data = rd->lockread.out.data;
884 lck->lock.level = RAW_LOCK_LOCK;
885 lck->lock.in.fnum = rd->lockread.in.fnum;
886 lck->lock.in.count = rd->lockread.in.count;
887 lck->lock.in.offset = rd->lockread.in.offset;
889 status = ntvfs->ops->lock(ntvfs, req, lck);
891 if (NT_STATUS_IS_OK(status)) {
892 status = ntvfs->ops->read(ntvfs, req, rd2);
893 rd->lockread.out.nread = rd2->generic.out.nread;
904 NTVFS close generic to any mapper
906 NTSTATUS ntvfs_map_close(struct smbsrv_request *req, union smb_close *cl,
907 struct ntvfs_module_context *ntvfs)
909 union smb_close *cl2;
911 cl2 = talloc_p(req, union smb_close);
913 return NT_STATUS_NO_MEMORY;
916 switch (cl2->generic.level) {
917 case RAW_CLOSE_CLOSE:
918 return NT_STATUS_INVALID_LEVEL;
920 case RAW_CLOSE_SPLCLOSE:
921 cl2->close.level = RAW_CLOSE_CLOSE;
922 cl2->close.in.fnum = cl->splclose.in.fnum;
926 return ntvfs->ops->close(ntvfs, req, cl2);