db4951fff05b89a8a3be727efc381400715b06ac
[bbaumbach/samba-autobuild/.git] / source4 / ntvfs / posix / pvfs_qfileinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    POSIX NTVFS backend - read
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 /*
28   approximately map a struct pvfs_filename to a generic fileinfo struct
29 */
30 static NTSTATUS pvfs_map_fileinfo(struct pvfs_state *pvfs, TALLOC_CTX *mem_ctx,
31                                   struct pvfs_filename *name, union smb_fileinfo *info)
32 {
33         switch (info->generic.level) {
34         case RAW_FILEINFO_GENERIC:
35                 return NT_STATUS_INVALID_LEVEL;
36
37         case RAW_FILEINFO_GETATTR:
38                 info->getattr.out.attrib     = name->dos.attrib;
39                 info->getattr.out.size       = name->st.st_size;
40                 info->getattr.out.write_time = nt_time_to_unix(name->dos.write_time);
41                 return NT_STATUS_OK;
42
43         case RAW_FILEINFO_GETATTRE:
44         case RAW_FILEINFO_STANDARD:
45                 info->standard.out.create_time = nt_time_to_unix(name->dos.create_time);
46                 info->standard.out.access_time = nt_time_to_unix(name->dos.access_time);
47                 info->standard.out.write_time  = nt_time_to_unix(name->dos.write_time);
48                 info->standard.out.size        = name->st.st_size;
49                 info->standard.out.alloc_size  = name->dos.alloc_size;
50                 info->standard.out.attrib      = name->dos.attrib;
51                 return NT_STATUS_OK;
52
53         case RAW_FILEINFO_EA_SIZE:
54                 info->ea_size.out.create_time = nt_time_to_unix(name->dos.create_time);
55                 info->ea_size.out.access_time = nt_time_to_unix(name->dos.access_time);
56                 info->ea_size.out.write_time  = nt_time_to_unix(name->dos.write_time);
57                 info->ea_size.out.size        = name->st.st_size;
58                 info->ea_size.out.alloc_size  = name->dos.alloc_size;
59                 info->ea_size.out.attrib      = name->dos.attrib;
60                 info->ea_size.out.ea_size     = name->dos.ea_size;
61                 return NT_STATUS_OK;
62
63         case RAW_FILEINFO_ALL_EAS:
64                 info->all_eas.out.num_eas = 0;
65                 info->all_eas.out.eas = NULL;
66                 return NT_STATUS_OK;
67
68         case RAW_FILEINFO_IS_NAME_VALID:
69                 return NT_STATUS_OK;
70
71         case RAW_FILEINFO_BASIC_INFO:
72         case RAW_FILEINFO_BASIC_INFORMATION:
73                 info->basic_info.out.create_time = name->dos.create_time;
74                 info->basic_info.out.access_time = name->dos.access_time;
75                 info->basic_info.out.write_time  = name->dos.write_time;
76                 info->basic_info.out.change_time = name->dos.change_time;
77                 info->basic_info.out.attrib      = name->dos.attrib;
78                 return NT_STATUS_OK;
79
80         case RAW_FILEINFO_STANDARD_INFO:
81         case RAW_FILEINFO_STANDARD_INFORMATION:
82                 info->standard_info.out.alloc_size     = name->dos.alloc_size;
83                 info->standard_info.out.size           = name->st.st_size;
84                 info->standard_info.out.nlink          = name->st.st_nlink;
85                 info->standard_info.out.delete_pending = 0;
86                 info->standard_info.out.directory   = 
87                         (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0;
88                 return NT_STATUS_OK;
89
90         case RAW_FILEINFO_EA_INFO:
91         case RAW_FILEINFO_EA_INFORMATION:
92                 info->ea_info.out.ea_size = name->dos.ea_size;
93                 return NT_STATUS_OK;
94
95         case RAW_FILEINFO_NAME_INFO:
96         case RAW_FILEINFO_NAME_INFORMATION:
97                 info->name_info.out.fname.s = name->original_name;
98                 return NT_STATUS_OK;
99
100         case RAW_FILEINFO_ALL_INFO:
101         case RAW_FILEINFO_ALL_INFORMATION:
102                 info->all_info.out.create_time    = name->dos.create_time;
103                 info->all_info.out.access_time    = name->dos.access_time;
104                 info->all_info.out.write_time     = name->dos.write_time;
105                 info->all_info.out.change_time    = name->dos.change_time;
106                 info->all_info.out.attrib         = name->dos.attrib;
107                 info->all_info.out.alloc_size     = name->dos.alloc_size;
108                 info->all_info.out.size           = name->st.st_size;
109                 info->all_info.out.nlink          = name->st.st_nlink;
110                 info->all_info.out.delete_pending = 0;
111                 info->all_info.out.directory      = 
112                         (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)? 1 : 0;
113                 info->all_info.out.ea_size        = name->dos.ea_size;
114                 info->all_info.out.fname.s        = name->original_name;
115                 return NT_STATUS_OK;
116
117         case RAW_FILEINFO_ALT_NAME_INFO:
118         case RAW_FILEINFO_ALT_NAME_INFORMATION:
119                 info->name_info.out.fname.s = pvfs_short_name(pvfs, name, name);
120                 return NT_STATUS_OK;
121
122         case RAW_FILEINFO_STREAM_INFO:
123         case RAW_FILEINFO_STREAM_INFORMATION:
124                 info->stream_info.out.num_streams = 1;
125                 info->stream_info.out.streams = talloc_array_p(mem_ctx, 
126                                                                struct stream_struct, 1);
127                 if (!info->stream_info.out.streams) {
128                         return NT_STATUS_NO_MEMORY;
129                 }
130                 info->stream_info.out.streams[0].size          = name->st.st_size;
131                 info->stream_info.out.streams[0].alloc_size    = name->dos.alloc_size;
132                 info->stream_info.out.streams[0].stream_name.s = 
133                         talloc_strdup(info->stream_info.out.streams, "::$DATA");
134                 return NT_STATUS_OK;
135
136         case RAW_FILEINFO_COMPRESSION_INFO:
137         case RAW_FILEINFO_COMPRESSION_INFORMATION:
138                 info->compression_info.out.compressed_size = name->st.st_size;
139                 info->compression_info.out.format          = 0;
140                 info->compression_info.out.unit_shift      = 0;
141                 info->compression_info.out.chunk_shift     = 0;
142                 info->compression_info.out.cluster_shift   = 0;
143                 return NT_STATUS_OK;
144
145         case RAW_FILEINFO_INTERNAL_INFORMATION:
146                 info->internal_information.out.file_id = name->dos.file_id;
147                 return NT_STATUS_OK;
148
149         case RAW_FILEINFO_ACCESS_INFORMATION:
150                 info->access_information.out.access_flags = 0;
151                 return NT_STATUS_OK;
152
153         case RAW_FILEINFO_POSITION_INFORMATION:
154                 info->position_information.out.position = 0;
155                 return NT_STATUS_OK;
156
157         case RAW_FILEINFO_MODE_INFORMATION:
158                 info->mode_information.out.mode = 0; /* what is this? */
159                 return NT_STATUS_OK;
160
161         case RAW_FILEINFO_ALIGNMENT_INFORMATION:
162                 info->alignment_information.out.alignment_requirement = 0;
163                 return NT_STATUS_OK;
164
165         case RAW_FILEINFO_NETWORK_OPEN_INFORMATION:
166                 info->network_open_information.out.create_time = name->dos.create_time;
167                 info->network_open_information.out.access_time = name->dos.access_time;
168                 info->network_open_information.out.write_time  = name->dos.write_time;
169                 info->network_open_information.out.change_time = name->dos.change_time;
170                 info->network_open_information.out.alloc_size  = name->dos.alloc_size;
171                 info->network_open_information.out.size        = name->st.st_size;
172                 info->network_open_information.out.attrib      = name->dos.attrib;
173                 return NT_STATUS_OK;
174
175         case RAW_FILEINFO_ATTRIBUTE_TAG_INFORMATION:
176                 info->attribute_tag_information.out.attrib      = name->dos.attrib;
177                 info->attribute_tag_information.out.reparse_tag = 0;
178                 return NT_STATUS_OK;
179         }
180
181         return NT_STATUS_INVALID_LEVEL;
182 }
183
184 /*
185   return info on a pathname
186 */
187 NTSTATUS pvfs_qpathinfo(struct ntvfs_module_context *ntvfs,
188                         struct smbsrv_request *req, union smb_fileinfo *info)
189 {
190         struct pvfs_state *pvfs = ntvfs->private_data;
191         struct pvfs_filename *name;
192         NTSTATUS status;
193
194         /* resolve the cifs name to a posix name */
195         status = pvfs_resolve_name(pvfs, req, info->generic.in.fname, 
196                                    PVFS_RESOLVE_NO_WILDCARD, &name);
197         if (!NT_STATUS_IS_OK(status)) {
198                 return status;
199         }
200
201         if (!name->exists) {
202                 return NT_STATUS_OBJECT_NAME_NOT_FOUND;
203         }
204
205         status = pvfs_map_fileinfo(pvfs, req, name, info);
206
207         return status;
208 }
209
210 /*
211   query info on a open file
212 */
213 NTSTATUS pvfs_qfileinfo(struct ntvfs_module_context *ntvfs,
214                         struct smbsrv_request *req, union smb_fileinfo *info)
215 {
216         struct pvfs_state *pvfs = ntvfs->private_data;
217         struct pvfs_file *f;
218         NTSTATUS status;
219
220         f = pvfs_find_fd(pvfs, req, info->generic.in.fnum);
221         if (!f) {
222                 return NT_STATUS_INVALID_HANDLE;
223         }
224
225         /* update the file information */
226         status = pvfs_resolve_name_fd(pvfs, f->fd, f->name);
227         if (!NT_STATUS_IS_OK(status)) {
228                 return status;
229         }
230         
231         status = pvfs_map_fileinfo(pvfs, req, f->name, info);
232
233         /* a qfileinfo can fill in a bit more info than a qpathinfo -
234            now modify the levels that need to be fixed up */
235         switch (info->generic.level) {
236         case RAW_FILEINFO_STANDARD_INFO:
237         case RAW_FILEINFO_STANDARD_INFORMATION:
238                 if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
239                         info->standard_info.out.delete_pending = 1;
240                         info->standard_info.out.nlink--;
241                 }
242                 break;
243
244         case RAW_FILEINFO_ALL_INFO:
245         case RAW_FILEINFO_ALL_INFORMATION:
246                 if (f->create_options & NTCREATEX_OPTIONS_DELETE_ON_CLOSE) {
247                         info->all_info.out.delete_pending = 1;
248                         info->all_info.out.nlink--;
249                 }
250                 break;
251
252         case RAW_FILEINFO_POSITION_INFORMATION:
253                 info->position_information.out.position = f->position;
254                 break;
255
256         case RAW_FILEINFO_ACCESS_INFORMATION:
257                 info->access_information.out.access_flags = f->access_mask;
258                 break;
259
260         default:
261                 break;
262         }
263         
264         return status;
265 }