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