import HEAD into svn+ssh://svn.samba.org/home/svn/samba/trunk
[metze/old/v3-2-winbind-ndr.git] / 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         DEBUG(4,("sending qpathinfo\n"));
73
74         if (!srv->no_pathinfo2 &&
75             cli_qpathinfo2(&srv->cli, path, c_time, a_time, m_time, NULL,
76                            size, mode, ino)) return True;
77
78         /* if this is NT then don't bother with the getatr */
79         if (srv->cli.capabilities & CAP_NT_SMBS) return False;
80
81         if (cli_getatr(&srv->cli, path, mode, size, m_time)) {
82                 a_time = c_time = m_time;
83                 srv->no_pathinfo2 = True;
84                 return True;
85         }
86         return False;
87 }
88
89
90 static struct print_job_info printjob;
91
92 /***************************************************** 
93 gather info from a printjob listing
94 *******************************************************/
95 static void smbw_printjob_stat(struct print_job_info *job)
96 {
97         if (strcmp(job->name, printjob.name) == 0) {
98                 printjob = *job;
99         }
100 }
101
102 /***************************************************** 
103 stat a printjob
104 *******************************************************/
105 int smbw_stat_printjob(struct smbw_server *srv,char *path,
106                        size_t *size, time_t *m_time)
107 {
108         if (path[0] == '\\') path++;
109
110         ZERO_STRUCT(printjob);
111
112         fstrcpy(printjob.name, path);
113         cli_print_queue(&srv->cli, smbw_printjob_stat);
114
115         if (size) {
116                 *size = printjob.size;
117         }
118         if (m_time) {
119                 *m_time = printjob.t;
120         }
121         return printjob.id;
122 }
123
124
125 /***************************************************** 
126 a wrapper for fstat()
127 *******************************************************/
128 int smbw_fstat(int fd, struct stat *st)
129 {
130         struct smbw_file *file;
131         time_t c_time, a_time, m_time;
132         size_t size;
133         uint16 mode;
134         SMB_INO_T ino = 0;
135
136         smbw_busy++;
137
138         ZERO_STRUCTP(st);
139
140         file = smbw_file(fd);
141         if (!file) {
142                 int ret = smbw_dir_fstat(fd, st);
143                 smbw_busy--;
144                 return ret;
145         }
146
147         if (!cli_qfileinfo(&file->srv->cli, file->f->cli_fd, 
148                            &mode, &size, &c_time, &a_time, &m_time, NULL,
149                            &ino) &&
150             !cli_getattrE(&file->srv->cli, file->f->cli_fd, 
151                           &mode, &size, &c_time, &a_time, &m_time)) {
152                 errno = EINVAL;
153                 smbw_busy--;
154                 return -1;
155         }
156
157         st->st_ino = ino;
158
159         smbw_setup_stat(st, file->f->fname, size, mode);
160
161         st->st_atime = a_time;
162         st->st_ctime = c_time;
163         st->st_mtime = m_time;
164         st->st_dev = file->srv->dev;
165
166         smbw_busy--;
167         return 0;
168 }
169
170
171 /***************************************************** 
172 a wrapper for stat()
173 *******************************************************/
174 int smbw_stat(const char *fname, struct stat *st)
175 {
176         struct smbw_server *srv;
177         fstring server, share;
178         pstring path;
179         time_t m_time=0, a_time=0, c_time=0;
180         size_t size=0;
181         uint16 mode=0;
182         SMB_INO_T ino = 0;
183         int result = 0;
184
185         ZERO_STRUCTP(st);
186
187         if (!fname) {
188                 errno = EINVAL;
189                 return -1;
190         }
191
192         DEBUG(4,("stat(%s)\n", fname));
193
194         smbw_init();
195
196         smbw_busy++;
197
198         /* work out what server they are after */
199         smbw_parse_path(fname, server, share, path);
200
201         /* get a connection to the server */
202         srv = smbw_server(server, share);
203         if (!srv) {
204
205                 /* For shares we aren't allowed to connect to, or no master
206                    browser found, return an empty directory */
207
208                 if ((server[0] && share[0] && !path[0] && errno == EACCES) ||
209                     (!path[0] && errno == ENOENT)) {
210                         mode = aDIR | aRONLY;
211                         smbw_setup_stat(st, path, size, mode);
212                         goto done;
213                 }
214
215                 /* smbw_server sets errno */
216                 result = -1;
217                 goto done;
218         }
219
220         DEBUG(4,("smbw_stat\n"));
221
222         if (strncmp(srv->cli.dev,"IPC",3) == 0) {
223                 mode = aDIR | aRONLY;
224         } else if (strncmp(srv->cli.dev,"LPT",3) == 0) {
225                 if (strcmp(path,"\\") == 0) {
226                         mode = aDIR | aRONLY;
227                 } else {
228                         mode = aRONLY;
229                         smbw_stat_printjob(srv, path, &size, &m_time);
230                         c_time = a_time = m_time;
231                 }
232         } else {
233                 if (!smbw_getatr(srv, path, 
234                                  &mode, &size, &c_time, &a_time, &m_time,
235                                  &ino)) {
236                         errno = smbw_errno(&srv->cli);
237                         result = -1;
238                         goto done;
239                 }
240         }
241
242         st->st_ino = ino;
243
244         smbw_setup_stat(st, path, size, mode);
245
246         st->st_atime = a_time;
247         st->st_ctime = c_time;
248         st->st_mtime = m_time;
249         st->st_dev = srv->dev;
250
251  done:
252         smbw_busy--;
253         return result;
254 }