2 Unix SMB/CIFS implementation.
4 POSIX NTVFS backend - setfileinfo
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"
25 #include "system/time.h"
28 set info on a open file
30 NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
31 struct smbsrv_request *req,
32 union smb_setfileinfo *info)
34 struct pvfs_state *pvfs = ntvfs->private_data;
35 struct utimbuf unix_times;
37 uint32_t create_options;
38 struct pvfs_filename newstats;
41 f = pvfs_find_fd(pvfs, req, info->generic.file.fnum);
43 return NT_STATUS_INVALID_HANDLE;
46 /* update the file information */
47 status = pvfs_resolve_name_fd(pvfs, f->fd, f->name);
48 if (!NT_STATUS_IS_OK(status)) {
52 /* we take a copy of the current file stats, then update
53 newstats in each of the elements below. At the end we
54 compare, and make any changes needed */
57 switch (info->generic.level) {
58 case RAW_SFILEINFO_SETATTR:
59 if (!null_time(info->setattr.in.write_time)) {
60 unix_to_nt_time(&newstats.dos.write_time, info->setattr.in.write_time);
62 if (info->setattr.in.attrib != FILE_ATTRIBUTE_NORMAL) {
63 newstats.dos.attrib = info->setattr.in.attrib;
67 case RAW_SFILEINFO_SETATTRE:
68 case RAW_SFILEINFO_STANDARD:
69 if (!null_time(info->setattre.in.create_time)) {
70 unix_to_nt_time(&newstats.dos.create_time, info->setattre.in.create_time);
72 if (!null_time(info->setattre.in.access_time)) {
73 unix_to_nt_time(&newstats.dos.access_time, info->setattre.in.access_time);
75 if (!null_time(info->setattre.in.write_time)) {
76 unix_to_nt_time(&newstats.dos.write_time, info->setattre.in.write_time);
80 case RAW_SFILEINFO_BASIC_INFO:
81 case RAW_SFILEINFO_BASIC_INFORMATION:
82 if (info->basic_info.in.create_time) {
83 newstats.dos.create_time = info->basic_info.in.create_time;
85 if (info->basic_info.in.access_time) {
86 newstats.dos.access_time = info->basic_info.in.access_time;
88 if (info->basic_info.in.write_time) {
89 newstats.dos.write_time = info->basic_info.in.write_time;
91 if (info->basic_info.in.change_time) {
92 newstats.dos.change_time = info->basic_info.in.change_time;
94 if (info->basic_info.in.attrib != 0) {
95 newstats.dos.attrib = info->basic_info.in.attrib;
99 case RAW_SFILEINFO_DISPOSITION_INFO:
100 case RAW_SFILEINFO_DISPOSITION_INFORMATION:
101 if (!(f->access_mask & STD_RIGHT_DELETE_ACCESS)) {
102 return NT_STATUS_ACCESS_DENIED;
104 create_options = f->create_options;
105 if (info->disposition_info.in.delete_on_close) {
106 create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
108 create_options &= ~NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
110 return pvfs_change_create_options(pvfs, req, f, create_options);
112 case RAW_SFILEINFO_ALLOCATION_INFO:
113 case RAW_SFILEINFO_ALLOCATION_INFORMATION:
114 newstats.dos.alloc_size = info->allocation_info.in.alloc_size;
117 case RAW_SFILEINFO_END_OF_FILE_INFO:
118 case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
119 newstats.st.st_size = info->end_of_file_info.in.size;
122 case RAW_SFILEINFO_POSITION_INFORMATION:
123 f->position = info->position_information.in.position;
127 return NT_STATUS_INVALID_LEVEL;
130 /* possibly change the file size */
131 if (newstats.st.st_size != f->name->st.st_size) {
132 if (f->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
133 return NT_STATUS_FILE_IS_A_DIRECTORY;
135 if (ftruncate(f->fd, newstats.st.st_size) == -1) {
136 return pvfs_map_errno(pvfs, errno);
140 /* possibly change the file timestamps */
141 ZERO_STRUCT(unix_times);
142 if (newstats.dos.access_time != f->name->dos.access_time) {
143 unix_times.actime = nt_time_to_unix(newstats.dos.access_time);
145 if (newstats.dos.write_time != f->name->dos.write_time) {
146 unix_times.modtime = nt_time_to_unix(newstats.dos.write_time);
148 if (unix_times.actime != 0 || unix_times.modtime != 0) {
149 if (utime(f->name->full_name, &unix_times) == -1) {
150 return pvfs_map_errno(pvfs, errno);
154 /* possibly change the attribute */
155 if (newstats.dos.attrib != f->name->dos.attrib) {
156 mode_t mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
157 if (f->name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY) {
158 /* ignore on directories for now */
161 if (fchmod(f->fd, mode) == -1) {
162 return pvfs_map_errno(pvfs, errno);
172 set info on a pathname
174 NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
175 struct smbsrv_request *req, union smb_setfileinfo *info)
177 struct pvfs_state *pvfs = ntvfs->private_data;
178 struct pvfs_filename *name;
179 struct pvfs_filename newstats;
181 struct utimbuf unix_times;
183 /* resolve the cifs name to a posix name */
184 status = pvfs_resolve_name(pvfs, req, info->generic.file.fname,
185 PVFS_RESOLVE_NO_WILDCARD, &name);
186 if (!NT_STATUS_IS_OK(status)) {
191 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
195 /* we take a copy of the current file stats, then update
196 newstats in each of the elements below. At the end we
197 compare, and make any changes needed */
200 switch (info->generic.level) {
201 case RAW_SFILEINFO_SETATTR:
202 if (!null_time(info->setattr.in.write_time)) {
203 unix_to_nt_time(&newstats.dos.write_time, info->setattr.in.write_time);
205 if (info->setattr.in.attrib != FILE_ATTRIBUTE_NORMAL) {
206 newstats.dos.attrib = info->setattr.in.attrib;
210 case RAW_SFILEINFO_SETATTRE:
211 case RAW_SFILEINFO_STANDARD:
212 if (!null_time(info->setattre.in.create_time)) {
213 unix_to_nt_time(&newstats.dos.create_time, info->setattre.in.create_time);
215 if (!null_time(info->setattre.in.access_time)) {
216 unix_to_nt_time(&newstats.dos.access_time, info->setattre.in.access_time);
218 if (!null_time(info->setattre.in.write_time)) {
219 unix_to_nt_time(&newstats.dos.write_time, info->setattre.in.write_time);
223 case RAW_SFILEINFO_BASIC_INFO:
224 case RAW_SFILEINFO_BASIC_INFORMATION:
225 if (info->basic_info.in.create_time) {
226 newstats.dos.create_time = info->basic_info.in.create_time;
228 if (info->basic_info.in.access_time) {
229 newstats.dos.access_time = info->basic_info.in.access_time;
231 if (info->basic_info.in.write_time) {
232 newstats.dos.write_time = info->basic_info.in.write_time;
234 if (info->basic_info.in.change_time) {
235 newstats.dos.change_time = info->basic_info.in.change_time;
237 if (info->basic_info.in.attrib != 0) {
238 newstats.dos.attrib = info->basic_info.in.attrib;
242 case RAW_SFILEINFO_ALLOCATION_INFO:
243 case RAW_SFILEINFO_ALLOCATION_INFORMATION:
244 newstats.dos.alloc_size = info->allocation_info.in.alloc_size;
247 case RAW_SFILEINFO_END_OF_FILE_INFO:
248 case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
249 newstats.st.st_size = info->end_of_file_info.in.size;
252 case RAW_SFILEINFO_DISPOSITION_INFO:
253 case RAW_SFILEINFO_DISPOSITION_INFORMATION:
254 case RAW_SFILEINFO_POSITION_INFORMATION:
258 return NT_STATUS_INVALID_LEVEL;
261 /* possibly change the file size */
262 if (newstats.st.st_size != name->st.st_size) {
263 if (truncate(name->full_name, newstats.st.st_size) == -1) {
264 return pvfs_map_errno(pvfs, errno);
268 /* possibly change the file timestamps */
269 ZERO_STRUCT(unix_times);
270 if (newstats.dos.access_time != name->dos.access_time) {
271 unix_times.actime = nt_time_to_unix(newstats.dos.access_time);
273 if (newstats.dos.write_time != name->dos.write_time) {
274 unix_times.modtime = nt_time_to_unix(newstats.dos.write_time);
276 if (unix_times.actime != 0 || unix_times.modtime != 0) {
277 if (utime(name->full_name, &unix_times) == -1) {
278 return pvfs_map_errno(pvfs, errno);
282 /* possibly change the attribute */
283 if (newstats.dos.attrib != name->dos.attrib) {
284 mode_t mode = pvfs_fileperms(pvfs, newstats.dos.attrib);
285 if (chmod(name->full_name, mode) == -1) {
286 return pvfs_map_errno(pvfs, errno);