6a9e2003f47f71b8bab6030cf590d223f34403f7
[jelmer/samba4-debian.git] / source / ntvfs / posix / pvfs_setfileinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    POSIX NTVFS backend - setfileinfo
5
6    Copyright (C) Andrew Tridgell 2004
7
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.
12    
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.
17    
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.
21 */
22
23 #include "include/includes.h"
24 #include "vfs_posix.h"
25
26 /*
27   set info on a open file
28 */
29 NTSTATUS pvfs_setfileinfo(struct ntvfs_module_context *ntvfs,
30                           struct smbsrv_request *req, 
31                           union smb_setfileinfo *info)
32 {
33         struct pvfs_state *pvfs = ntvfs->private_data;
34         struct utimbuf unix_times;
35         struct pvfs_file *f;
36         uint32_t create_options;
37
38         f = pvfs_find_fd(pvfs, req, info->generic.file.fnum);
39         if (!f) {
40                 return NT_STATUS_INVALID_HANDLE;
41         }
42
43         switch (info->generic.level) {
44         case RAW_SFILEINFO_END_OF_FILE_INFO:
45         case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
46                 if (ftruncate(f->fd,
47                               info->end_of_file_info.in.size) == -1) {
48                         return pvfs_map_errno(pvfs, errno);
49                 }
50                 break;
51
52         case RAW_SFILEINFO_SETATTRE:
53                 unix_times.actime = info->setattre.in.access_time;
54                 unix_times.modtime = info->setattre.in.write_time;
55         
56                 if (unix_times.actime == 0 && unix_times.modtime == 0) {
57                         break;
58                 } 
59
60                 /* set modify time = to access time if modify time was 0 */
61                 if (unix_times.actime != 0 && unix_times.modtime == 0) {
62                         unix_times.modtime = unix_times.actime;
63                 }
64
65                 /* Set the date on this file */
66                 if (utime(f->name->full_name, &unix_times) == -1) {
67                         return pvfs_map_errno(pvfs, errno);
68                 }
69                 break;
70
71         case RAW_SFILEINFO_DISPOSITION_INFO:
72         case RAW_SFILEINFO_DISPOSITION_INFORMATION:
73                 if (!(f->access_mask & STD_RIGHT_DELETE_ACCESS)) {
74                         return NT_STATUS_ACCESS_DENIED;
75                 }
76                 create_options = f->create_options;
77                 if (info->disposition_info.in.delete_on_close) {
78                         create_options |= NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
79                 } else {
80                         create_options &= ~NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
81                 }
82                 return pvfs_change_create_options(pvfs, req, f, create_options);
83
84         case RAW_SFILEINFO_POSITION_INFORMATION:
85                 f->position = info->position_information.in.position;
86                 break;
87         }
88
89         return NT_STATUS_OK;
90 }
91
92
93 /*
94   set info on a pathname
95 */
96 NTSTATUS pvfs_setpathinfo(struct ntvfs_module_context *ntvfs,
97                           struct smbsrv_request *req, union smb_setfileinfo *info)
98 {
99         struct pvfs_state *pvfs = ntvfs->private_data;
100         struct pvfs_filename *name;
101         NTSTATUS status;
102         struct utimbuf unix_times;
103
104         /* resolve the cifs name to a posix name */
105         status = pvfs_resolve_name(pvfs, req, info->generic.file.fname, 
106                                    PVFS_RESOLVE_NO_WILDCARD, &name);
107         if (!NT_STATUS_IS_OK(status)) {
108                 return status;
109         }
110
111         if (!name->exists) {
112                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
113         }
114
115         switch (info->generic.level) {
116         case RAW_SFILEINFO_END_OF_FILE_INFO:
117         case RAW_SFILEINFO_END_OF_FILE_INFORMATION:
118                 if (truncate(name->full_name,
119                               info->end_of_file_info.in.size) == -1) {
120                         return pvfs_map_errno(pvfs, errno);
121                 }
122                 break;
123
124         case RAW_SFILEINFO_SETATTRE:
125                 unix_times.actime = info->setattre.in.access_time;
126                 unix_times.modtime = info->setattre.in.write_time;
127         
128                 if (unix_times.actime == 0 && unix_times.modtime == 0) {
129                         break;
130                 } 
131
132                 /* set modify time = to access time if modify time was 0 */
133                 if (unix_times.actime != 0 && unix_times.modtime == 0) {
134                         unix_times.modtime = unix_times.actime;
135                 }
136
137                 /* Set the date on this file */
138                 if (utime(name->full_name, &unix_times) == -1) {
139                         return NT_STATUS_ACCESS_DENIED;
140                 }
141                 break;
142
143         case RAW_SFILEINFO_DISPOSITION_INFO:
144         case RAW_SFILEINFO_DISPOSITION_INFORMATION:
145                 return NT_STATUS_INVALID_PARAMETER;
146
147         case RAW_SFILEINFO_POSITION_INFORMATION:
148                 return NT_STATUS_OK;
149         }
150
151         return NT_STATUS_INVALID_LEVEL;
152 }
153