Initial import
[samba] / source / 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 #ifdef HAVE_STAT_ST_BLKSIZE
45         st->st_blksize = 512;
46 #endif
47 #ifdef HAVE_STAT_ST_BLOCKS
48         st->st_blocks = (size+511)/512;
49 #endif
50         st->st_uid = getuid();
51         st->st_gid = getgid();
52         if (IS_DOS_DIR(mode)) {
53                 st->st_nlink = 2;
54         } else {
55                 st->st_nlink = 1;
56         }
57         if (st->st_ino == 0) {
58                 st->st_ino = smbw_inode(fname);
59         }
60 }
61
62
63 /***************************************************** 
64 try to do a QPATHINFO and if that fails then do a getatr
65 this is needed because win95 sometimes refuses the qpathinfo
66 *******************************************************/
67 BOOL smbw_getatr(struct smbw_server *srv, char *path, 
68                  uint16 *mode, size_t *size, 
69                  time_t *c_time, time_t *a_time, time_t *m_time,
70                  SMB_INO_T *ino)
71 {
72         time_t c_a_m_time;
73         /*
74          * "size" (size_t) is only 32 bits.  Rather than change the interface
75          * in this code as we change cli_qpathinfo2() and cli_getatr() to
76          * support 64-bit file sizes, we'll use a temporary variable and
77          * maintain the interface size_t.  At some point, someone may want to
78          * change the interface as well.  djl
79          */
80         SMB_OFF_T fullsize;
81
82         DEBUG(4,("sending qpathinfo\n"));
83
84         if (!srv->no_pathinfo2 &&
85             cli_qpathinfo2(&srv->cli, path, c_time, a_time, m_time, NULL,
86                            &fullsize, mode, ino)) {
87                 if (size != NULL) *size = (size_t) fullsize;
88                 return True;
89         }
90
91         /* if this is NT then don't bother with the getatr */
92         if (srv->cli.capabilities & CAP_NT_SMBS) return False;
93
94         if (cli_getatr(&srv->cli, path, mode, &fullsize, &c_a_m_time)) {
95                 if (a_time != NULL) *a_time = c_a_m_time;
96                 if (c_time != NULL) *a_time = c_a_m_time;
97                 if (m_time != NULL) *a_time = c_a_m_time;
98                 if (size != NULL) *size = (size_t) fullsize;
99                 srv->no_pathinfo2 = True;
100                 return True;
101         }
102         return False;
103 }
104
105
106 static struct print_job_info printjob;
107
108 /***************************************************** 
109 gather info from a printjob listing
110 *******************************************************/
111 static void smbw_printjob_stat(struct print_job_info *job)
112 {
113         if (strcmp(job->name, printjob.name) == 0) {
114                 printjob = *job;
115         }
116 }
117
118 /***************************************************** 
119 stat a printjob
120 *******************************************************/
121 int smbw_stat_printjob(struct smbw_server *srv,char *path,
122                        size_t *size, time_t *m_time)
123 {
124         if (path[0] == '\\') path++;
125
126         ZERO_STRUCT(printjob);
127
128         fstrcpy(printjob.name, path);
129         cli_print_queue(&srv->cli, smbw_printjob_stat);
130
131         if (size) {
132                 *size = printjob.size;
133         }
134         if (m_time) {
135                 *m_time = printjob.t;
136         }
137         return printjob.id;
138 }
139
140
141 /***************************************************** 
142 a wrapper for fstat()
143 *******************************************************/
144 int smbw_fstat(int fd, struct stat *st)
145 {
146         struct smbw_file *file;
147         time_t c_time, a_time, m_time;
148         SMB_OFF_T size;
149         uint16 mode;
150         SMB_INO_T ino = 0;
151
152         smbw_busy++;
153
154         ZERO_STRUCTP(st);
155
156         file = smbw_file(fd);
157         if (!file) {
158                 int ret = smbw_dir_fstat(fd, st);
159                 smbw_busy--;
160                 return ret;
161         }
162
163         if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd, 
164                            &mode, &size, &c_time, &a_time, &m_time, NULL,
165                            &ino) &&
166             !cli_getattrE(&file->srv->cli, file->f->cli_fd, 
167                           &mode, &size, &c_time, &a_time, &m_time)) {
168                 errno = EINVAL;
169                 smbw_busy--;
170                 return -1;
171         }
172
173         st->st_ino = ino;
174
175         smbw_setup_stat(st, file->f->fname, size, mode);
176
177         st->st_atime = a_time;
178         st->st_ctime = c_time;
179         st->st_mtime = m_time;
180         st->st_dev = file->srv->dev;
181
182         smbw_busy--;
183         return 0;
184 }
185
186
187 /***************************************************** 
188 a wrapper for stat()
189 *******************************************************/
190 int smbw_stat(const char *fname, struct stat *st)
191 {
192         struct smbw_server *srv;
193         fstring server, share;
194         pstring path;
195         time_t m_time=0, a_time=0, c_time=0;
196         size_t size=0;
197         uint16 mode=0;
198         SMB_INO_T ino = 0;
199         int result = 0;
200
201         ZERO_STRUCTP(st);
202
203         if (!fname) {
204                 errno = EINVAL;
205                 return -1;
206         }
207
208         DEBUG(4,("stat(%s)\n", fname));
209
210         smbw_init();
211
212         smbw_busy++;
213
214         /* work out what server they are after */
215         smbw_parse_path(fname, server, share, path);
216
217         /* get a connection to the server */
218         srv = smbw_server(server, share);
219         if (!srv) {
220
221                 /* For shares we aren't allowed to connect to, or no master
222                    browser found, return an empty directory */
223
224                 if ((server[0] && share[0] && !path[0] && errno == EACCES) ||
225                     (!path[0] && errno == ENOENT)) {
226                         mode = aDIR | aRONLY;
227                         smbw_setup_stat(st, path, size, mode);
228                         goto done;
229                 }
230
231                 /* smbw_server sets errno */
232                 result = -1;
233                 goto done;
234         }
235
236         DEBUG(4,("smbw_stat\n"));
237
238         if (strncmp(srv->cli.dev,"IPC",3) == 0) {
239                 mode = aDIR | aRONLY;
240         } else if (strncmp(srv->cli.dev,"LPT",3) == 0) {
241                 if (strcmp(path,"\\") == 0) {
242                         mode = aDIR | aRONLY;
243                 } else {
244                         mode = aRONLY;
245                         smbw_stat_printjob(srv, path, &size, &m_time);
246                         c_time = a_time = m_time;
247                 }
248         } else {
249                 if (!smbw_getatr(srv, path, 
250                                  &mode, &size, &c_time, &a_time, &m_time,
251                                  &ino)) {
252                         errno = smbw_errno(&srv->cli);
253                         result = -1;
254                         goto done;
255                 }
256         }
257
258         st->st_ino = ino;
259
260         smbw_setup_stat(st, path, size, mode);
261
262         st->st_atime = a_time;
263         st->st_ctime = c_time;
264         st->st_mtime = m_time;
265         st->st_dev = srv->dev;
266
267  done:
268         smbw_busy--;
269         return result;
270 }