Removed version number from file header.
[jra/samba/.git] / source3 / smbwrapper / smbw_stat.c
1 /* 
2    Unix SMB/CIFS implementation.
3    SMB wrapper stat functions
4    Copyright (C) Andrew Tridgell 1998
5    
6    This program is free software; you can redistribute it and/or modify
7    it under the terms of the GNU General Public License as published by
8    the Free Software Foundation; either version 2 of the License, or
9    (at your option) any later version.
10    
11    This program is distributed in the hope that it will be useful,
12    but WITHOUT ANY WARRANTY; without even the implied warranty of
13    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14    GNU General Public License for more details.
15    
16    You should have received a copy of the GNU General Public License
17    along with this program; if not, write to the Free Software
18    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19 */
20
21 #include "includes.h"
22
23 extern int smbw_busy;
24
25 /***************************************************** 
26 setup basic info in a stat structure
27 *******************************************************/
28 void smbw_setup_stat(struct stat *st, char *fname, size_t size, int mode)
29 {
30         st->st_mode = 0;
31
32         if (IS_DOS_DIR(mode)) {
33                 st->st_mode = SMBW_DIR_MODE;
34         } else {
35                 st->st_mode = SMBW_FILE_MODE;
36         }
37
38         if (IS_DOS_ARCHIVE(mode)) st->st_mode |= S_IXUSR;
39         if (IS_DOS_SYSTEM(mode)) st->st_mode |= S_IXGRP;
40         if (IS_DOS_HIDDEN(mode)) st->st_mode |= S_IXOTH;
41         if (!IS_DOS_READONLY(mode)) st->st_mode |= S_IWUSR;
42
43         st->st_size = size;
44         st->st_blksize = 512;
45         st->st_blocks = (size+511)/512;
46         st->st_uid = getuid();
47         st->st_gid = getgid();
48         if (IS_DOS_DIR(mode)) {
49                 st->st_nlink = 2;
50         } else {
51                 st->st_nlink = 1;
52         }
53         if (st->st_ino == 0) {
54                 st->st_ino = smbw_inode(fname);
55         }
56 }
57
58
59 /***************************************************** 
60 try to do a QPATHINFO and if that fails then do a getatr
61 this is needed because win95 sometimes refuses the qpathinfo
62 *******************************************************/
63 BOOL smbw_getatr(struct smbw_server *srv, char *path, 
64                  uint16 *mode, size_t *size, 
65                  time_t *c_time, time_t *a_time, time_t *m_time,
66                  SMB_INO_T *ino)
67 {
68         DEBUG(4,("sending qpathinfo\n"));
69
70         if (!srv->no_pathinfo2 &&
71             cli_qpathinfo2(&srv->cli, path, c_time, a_time, m_time, NULL,
72                            size, mode, ino)) return True;
73
74         /* if this is NT then don't bother with the getatr */
75         if (srv->cli.capabilities & CAP_NT_SMBS) return False;
76
77         if (cli_getatr(&srv->cli, path, mode, size, m_time)) {
78                 a_time = c_time = m_time;
79                 srv->no_pathinfo2 = True;
80                 return True;
81         }
82         return False;
83 }
84
85
86 static struct print_job_info printjob;
87
88 /***************************************************** 
89 gather info from a printjob listing
90 *******************************************************/
91 static void smbw_printjob_stat(struct print_job_info *job)
92 {
93         if (strcmp(job->name, printjob.name) == 0) {
94                 printjob = *job;
95         }
96 }
97
98 /***************************************************** 
99 stat a printjob
100 *******************************************************/
101 int smbw_stat_printjob(struct smbw_server *srv,char *path,
102                        size_t *size, time_t *m_time)
103 {
104         if (path[0] == '\\') path++;
105
106         ZERO_STRUCT(printjob);
107
108         fstrcpy(printjob.name, path);
109         cli_print_queue(&srv->cli, smbw_printjob_stat);
110
111         if (size) {
112                 *size = printjob.size;
113         }
114         if (m_time) {
115                 *m_time = printjob.t;
116         }
117         return printjob.id;
118 }
119
120
121 /***************************************************** 
122 a wrapper for fstat()
123 *******************************************************/
124 int smbw_fstat(int fd, struct stat *st)
125 {
126         struct smbw_file *file;
127         time_t c_time, a_time, m_time;
128         size_t size;
129         uint16 mode;
130         SMB_INO_T ino = 0;
131
132         smbw_busy++;
133
134         ZERO_STRUCTP(st);
135
136         file = smbw_file(fd);
137         if (!file) {
138                 int ret = smbw_dir_fstat(fd, st);
139                 smbw_busy--;
140                 return ret;
141         }
142
143         if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd, 
144                            &mode, &size, &c_time, &a_time, &m_time, NULL,
145                            &ino) &&
146             !cli_getattrE(&file->srv->cli, file->f->cli_fd, 
147                           &mode, &size, &c_time, &a_time, &m_time)) {
148                 errno = EINVAL;
149                 smbw_busy--;
150                 return -1;
151         }
152
153         st->st_ino = ino;
154
155         smbw_setup_stat(st, file->f->fname, size, mode);
156
157         st->st_atime = a_time;
158         st->st_ctime = c_time;
159         st->st_mtime = m_time;
160         st->st_dev = file->srv->dev;
161
162         smbw_busy--;
163         return 0;
164 }
165
166
167 /***************************************************** 
168 a wrapper for stat()
169 *******************************************************/
170 int smbw_stat(const char *fname, struct stat *st)
171 {
172         struct smbw_server *srv;
173         fstring server, share;
174         pstring path;
175         time_t m_time=0, a_time=0, c_time=0;
176         size_t size=0;
177         uint16 mode=0;
178         SMB_INO_T ino = 0;
179         int result = 0;
180
181         ZERO_STRUCTP(st);
182
183         if (!fname) {
184                 errno = EINVAL;
185                 return -1;
186         }
187
188         DEBUG(4,("stat(%s)\n", fname));
189
190         smbw_init();
191
192         smbw_busy++;
193
194         /* work out what server they are after */
195         smbw_parse_path(fname, server, share, path);
196
197         /* get a connection to the server */
198         srv = smbw_server(server, share);
199         if (!srv) {
200
201                 /* For shares we aren't allowed to connect to, or no master
202                    browser found, return an empty directory */
203
204                 if ((server[0] && share[0] && !path[0] && errno == EACCES) ||
205                     (!path[0] && errno == ENOENT)) {
206                         mode = aDIR | aRONLY;
207                         smbw_setup_stat(st, path, size, mode);
208                         goto done;
209                 }
210
211                 /* smbw_server sets errno */
212                 result = -1;
213                 goto done;
214         }
215
216         DEBUG(4,("smbw_stat\n"));
217
218         if (strncmp(srv->cli.dev,"IPC",3) == 0) {
219                 mode = aDIR | aRONLY;
220         } else if (strncmp(srv->cli.dev,"LPT",3) == 0) {
221                 if (strcmp(path,"\\") == 0) {
222                         mode = aDIR | aRONLY;
223                 } else {
224                         mode = aRONLY;
225                         smbw_stat_printjob(srv, path, &size, &m_time);
226                         c_time = a_time = m_time;
227                 }
228         } else {
229                 if (!smbw_getatr(srv, path, 
230                                  &mode, &size, &c_time, &a_time, &m_time,
231                                  &ino)) {
232                         errno = smbw_errno(&srv->cli);
233                         result = -1;
234                         goto done;
235                 }
236         }
237
238         st->st_ino = ino;
239
240         smbw_setup_stat(st, path, size, mode);
241
242         st->st_atime = a_time;
243         st->st_ctime = c_time;
244         st->st_mtime = m_time;
245         st->st_dev = srv->dev;
246
247  done:
248         smbw_busy--;
249         return result;
250 }