2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - open and close
6 Copyright (C) Andrew Tridgell 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 #include "include/includes.h"
24 #include "vfs_posix.h"
28 find open file handle given fnum
30 struct pvfs_file *pvfs_find_fd(struct pvfs_state *pvfs, uint16_t fnum)
33 for (f=pvfs->open_files;f;f=f->next) {
34 if (f->fnum == fnum) {
42 by using a destructor we make sure that abnormal cleanup will not
43 leak file descriptors (assuming at least the top level pointer is freed, which
44 will cascade down to here)
46 static int pvfs_fd_destructor(void *p)
48 struct pvfs_file *f = p;
58 TODO: this is a temporary implementation derived from the simple backend
59 its purpose is to allow other tests to run
61 NTSTATUS pvfs_open(struct smbsrv_request *req, union smb_open *io)
63 NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
65 struct pvfs_filename *name;
69 if (io->generic.level != RAW_OPEN_GENERIC) {
70 return ntvfs_map_open(req, io, pvfs->ops);
73 /* resolve the cifs name to a posix name */
74 status = pvfs_resolve_name(pvfs, req, io->ntcreatex.in.fname,
75 PVFS_RESOLVE_NO_WILDCARD, &name);
76 if (!NT_STATUS_IS_OK(status)) {
80 switch (io->generic.in.open_disposition) {
81 case NTCREATEX_DISP_SUPERSEDE:
82 case NTCREATEX_DISP_OVERWRITE_IF:
83 flags = O_CREAT | O_TRUNC;
85 case NTCREATEX_DISP_OPEN:
86 case NTCREATEX_DISP_OVERWRITE:
89 case NTCREATEX_DISP_CREATE:
90 flags = O_CREAT | O_EXCL;
92 case NTCREATEX_DISP_OPEN_IF:
102 /* we need to do this differently to support systems without O_DIRECTORY */
104 #define O_DIRECTORY 0
107 if (io->generic.in.create_options & NTCREATEX_OPTIONS_DIRECTORY) {
108 flags = O_RDONLY | O_DIRECTORY;
109 if (pvfs->flags & PVFS_FLAG_READONLY) {
112 switch (io->generic.in.open_disposition) {
113 case NTCREATEX_DISP_CREATE:
114 if (mkdir(name->full_name, 0755) == -1) {
115 return pvfs_map_errno(pvfs,errno);
118 case NTCREATEX_DISP_OPEN_IF:
119 if (mkdir(name->full_name, 0755) == -1 && errno != EEXIST) {
120 return pvfs_map_errno(pvfs,errno);
127 fd = open(name->full_name, flags, 0644);
131 return pvfs_map_errno(pvfs,errno);
134 f = talloc_p(pvfs, struct pvfs_file);
137 return NT_STATUS_NO_MEMORY;
140 /* re-resolve the open fd */
141 status = pvfs_resolve_name_fd(pvfs, fd, name);
142 if (!NT_STATUS_IS_OK(status)) {
148 f->name = talloc_steal(f, name);
150 /* setup a destructor to avoid file descriptor leaks on
151 abnormal termination */
152 talloc_set_destructor(f, pvfs_fd_destructor);
154 DLIST_ADD(pvfs->open_files, f);
156 ZERO_STRUCT(io->generic.out);
158 io->generic.out.create_time = name->dos.create_time;
159 io->generic.out.access_time = name->dos.access_time;
160 io->generic.out.write_time = name->dos.write_time;
161 io->generic.out.change_time = name->dos.change_time;
162 io->generic.out.fnum = f->fnum;
163 io->generic.out.alloc_size = name->dos.alloc_size;
164 io->generic.out.size = name->st.st_size;
165 io->generic.out.attrib = name->dos.attrib;
166 io->generic.out.is_directory = (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)?1:0;
175 NTSTATUS pvfs_close(struct smbsrv_request *req, union smb_close *io)
177 NTVFS_GET_PRIVATE(pvfs_state, pvfs, req);
181 if (io->generic.level != RAW_CLOSE_CLOSE) {
182 /* we need a mapping function */
183 return NT_STATUS_INVALID_LEVEL;
186 f = pvfs_find_fd(pvfs, io->close.in.fnum);
188 return NT_STATUS_INVALID_HANDLE;
191 if (close(f->fd) != 0) {
192 status = pvfs_map_errno(pvfs, errno);
194 status = NT_STATUS_OK;
197 talloc_set_destructor(f, NULL);
199 DLIST_REMOVE(pvfs->open_files, f);