r3441: some include file cleanups and general housekeeping
[ira/wip.git] / source4 / libcli / clifile.c
1 /* 
2    Unix SMB/CIFS implementation.
3    client file operations
4    Copyright (C) Andrew Tridgell 1994-1998
5    Copyright (C) Jeremy Allison 2001-2002
6    Copyright (C) James Myers 2003
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 "includes.h"
24 #include "libcli/raw/libcliraw.h"
25
26 /****************************************************************************
27  Hard/Symlink a file (UNIX extensions).
28 ****************************************************************************/
29
30 static NTSTATUS smbcli_link_internal(struct smbcli_tree *tree, 
31                                   const char *fname_src, 
32                                   const char *fname_dst, BOOL hard_link)
33 {
34         union smb_setfileinfo parms;
35         NTSTATUS status;
36
37         if (hard_link) {
38                 parms.generic.level = RAW_SFILEINFO_UNIX_HLINK;
39                 parms.unix_hlink.file.fname = fname_src;
40                 parms.unix_hlink.in.link_dest = fname_dst;
41         } else {
42                 parms.generic.level = RAW_SFILEINFO_UNIX_LINK;
43                 parms.unix_link.file.fname = fname_src;
44                 parms.unix_link.in.link_dest = fname_dst;
45         }
46         
47         status = smb_raw_setpathinfo(tree, &parms);
48
49         return status;
50 }
51
52 /****************************************************************************
53  Map standard UNIX permissions onto wire representations.
54 ****************************************************************************/
55 uint32_t unix_perms_to_wire(mode_t perms)
56 {
57         uint_t ret = 0;
58
59         ret |= ((perms & S_IXOTH) ?  UNIX_X_OTH : 0);
60         ret |= ((perms & S_IWOTH) ?  UNIX_W_OTH : 0);
61         ret |= ((perms & S_IROTH) ?  UNIX_R_OTH : 0);
62         ret |= ((perms & S_IXGRP) ?  UNIX_X_GRP : 0);
63         ret |= ((perms & S_IWGRP) ?  UNIX_W_GRP : 0);
64         ret |= ((perms & S_IRGRP) ?  UNIX_R_GRP : 0);
65         ret |= ((perms & S_IXUSR) ?  UNIX_X_USR : 0);
66         ret |= ((perms & S_IWUSR) ?  UNIX_W_USR : 0);
67         ret |= ((perms & S_IRUSR) ?  UNIX_R_USR : 0);
68 #ifdef S_ISVTX
69         ret |= ((perms & S_ISVTX) ?  UNIX_STICKY : 0);
70 #endif
71 #ifdef S_ISGID
72         ret |= ((perms & S_ISGID) ?  UNIX_SET_GID : 0);
73 #endif
74 #ifdef S_ISUID
75         ret |= ((perms & S_ISUID) ?  UNIX_SET_UID : 0);
76 #endif
77         return ret;
78 }
79
80 /****************************************************************************
81  Symlink a file (UNIX extensions).
82 ****************************************************************************/
83 NTSTATUS smbcli_unix_symlink(struct smbcli_tree *tree, const char *fname_src, 
84                           const char *fname_dst)
85 {
86         return smbcli_link_internal(tree, fname_src, fname_dst, False);
87 }
88
89 /****************************************************************************
90  Hard a file (UNIX extensions).
91 ****************************************************************************/
92 NTSTATUS smbcli_unix_hardlink(struct smbcli_tree *tree, const char *fname_src, 
93                            const char *fname_dst)
94 {
95         return smbcli_link_internal(tree, fname_src, fname_dst, True);
96 }
97
98
99 /****************************************************************************
100  Chmod or chown a file internal (UNIX extensions).
101 ****************************************************************************/
102 static NTSTATUS smbcli_unix_chmod_chown_internal(struct smbcli_tree *tree, 
103                                               const char *fname, 
104                                               uint32_t mode, uint32_t uid, 
105                                               uint32_t gid)
106 {
107         union smb_setfileinfo parms;
108         NTSTATUS status;
109
110         parms.generic.level = SMB_SFILEINFO_UNIX_BASIC;
111         parms.unix_basic.file.fname = fname;
112         parms.unix_basic.in.uid = uid;
113         parms.unix_basic.in.gid = gid;
114         parms.unix_basic.in.mode = mode;
115         
116         status = smb_raw_setpathinfo(tree, &parms);
117
118         return status;
119 }
120
121 /****************************************************************************
122  chmod a file (UNIX extensions).
123 ****************************************************************************/
124
125 NTSTATUS smbcli_unix_chmod(struct smbcli_tree *tree, const char *fname, mode_t mode)
126 {
127         return smbcli_unix_chmod_chown_internal(tree, fname, 
128                                              unix_perms_to_wire(mode), 
129                                              SMB_UID_NO_CHANGE, 
130                                              SMB_GID_NO_CHANGE);
131 }
132
133 /****************************************************************************
134  chown a file (UNIX extensions).
135 ****************************************************************************/
136 NTSTATUS smbcli_unix_chown(struct smbcli_tree *tree, const char *fname, uid_t uid, 
137                         gid_t gid)
138 {
139         return smbcli_unix_chmod_chown_internal(tree, fname, SMB_MODE_NO_CHANGE, 
140                                              (uint32_t)uid, (uint32_t)gid);
141 }
142
143
144 /****************************************************************************
145  Rename a file.
146 ****************************************************************************/
147 NTSTATUS smbcli_rename(struct smbcli_tree *tree, const char *fname_src, 
148                     const char *fname_dst)
149 {
150         union smb_rename parms;
151
152         parms.generic.level = RAW_RENAME_RENAME;
153         parms.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
154         parms.rename.in.pattern1 = fname_src;
155         parms.rename.in.pattern2 = fname_dst;
156
157         return smb_raw_rename(tree, &parms);
158 }
159
160
161 /****************************************************************************
162  Delete a file.
163 ****************************************************************************/
164 NTSTATUS smbcli_unlink(struct smbcli_tree *tree, const char *fname)
165 {
166         struct smb_unlink parms;
167
168         parms.in.pattern = fname;
169         if (strchr(fname, '*')) {
170                 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
171         } else {
172                 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
173         }
174
175         return smb_raw_unlink(tree, &parms);
176 }
177
178 /****************************************************************************
179  Create a directory.
180 ****************************************************************************/
181 NTSTATUS smbcli_mkdir(struct smbcli_tree *tree, const char *dname)
182 {
183         union smb_mkdir parms;
184
185         parms.mkdir.level = RAW_MKDIR_MKDIR;
186         parms.mkdir.in.path = dname;
187
188         return smb_raw_mkdir(tree, &parms);
189 }
190
191
192 /****************************************************************************
193  Remove a directory.
194 ****************************************************************************/
195 NTSTATUS smbcli_rmdir(struct smbcli_tree *tree, const char *dname)
196 {
197         struct smb_rmdir parms;
198
199         parms.in.path = dname;
200
201         return smb_raw_rmdir(tree, &parms);
202 }
203
204
205 /****************************************************************************
206  Set or clear the delete on close flag.
207 ****************************************************************************/
208 NTSTATUS smbcli_nt_delete_on_close(struct smbcli_tree *tree, int fnum, BOOL flag)
209 {
210         union smb_setfileinfo parms;
211         NTSTATUS status;
212
213         parms.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
214         parms.disposition_info.file.fnum = fnum;
215         parms.disposition_info.in.delete_on_close = flag;
216         
217         status = smb_raw_setfileinfo(tree, &parms);
218
219         return status;
220 }
221
222
223 /****************************************************************************
224  Create/open a file - exposing the full horror of the NT API :-).
225  Used in CIFS-on-CIFS NTVFS.
226 ****************************************************************************/
227 int smbcli_nt_create_full(struct smbcli_tree *tree, const char *fname,
228                        uint32_t CreatFlags, uint32_t DesiredAccess,
229                        uint32_t FileAttributes, uint32_t ShareAccess,
230                        uint32_t CreateDisposition, uint32_t CreateOptions,
231                        uint8_t SecurityFlags)
232 {
233         union smb_open open_parms;
234         TALLOC_CTX *mem_ctx;
235         NTSTATUS status;
236
237         mem_ctx = talloc_init("raw_open");
238         if (!mem_ctx) return -1;
239
240         open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
241         open_parms.ntcreatex.in.flags = CreatFlags;
242         open_parms.ntcreatex.in.root_fid = 0;
243         open_parms.ntcreatex.in.access_mask = DesiredAccess;
244         open_parms.ntcreatex.in.file_attr = FileAttributes;
245         open_parms.ntcreatex.in.alloc_size = 0;
246         open_parms.ntcreatex.in.share_access = ShareAccess;
247         open_parms.ntcreatex.in.open_disposition = CreateDisposition;
248         open_parms.ntcreatex.in.create_options = CreateOptions;
249         open_parms.ntcreatex.in.impersonation = 0;
250         open_parms.ntcreatex.in.security_flags = SecurityFlags;
251         open_parms.ntcreatex.in.fname = fname;
252
253         status = smb_raw_open(tree, mem_ctx, &open_parms);
254         talloc_destroy(mem_ctx);
255
256         if (NT_STATUS_IS_OK(status)) {
257                 return open_parms.ntcreatex.out.fnum;
258         }
259         
260         return -1;
261 }
262
263
264 /****************************************************************************
265  Open a file (using SMBopenx)
266  WARNING: if you open with O_WRONLY then getattrE won't work!
267 ****************************************************************************/
268 int smbcli_open(struct smbcli_tree *tree, const char *fname, int flags, 
269              int share_mode)
270 {
271         union smb_open open_parms;
272         uint_t openfn=0;
273         uint_t accessmode=0;
274         TALLOC_CTX *mem_ctx;
275         NTSTATUS status;
276
277         mem_ctx = talloc_init("raw_open");
278         if (!mem_ctx) return -1;
279
280         if (flags & O_CREAT) {
281                 openfn |= OPENX_OPEN_FUNC_CREATE;
282         }
283         if (!(flags & O_EXCL)) {
284                 if (flags & O_TRUNC) {
285                         openfn |= OPENX_OPEN_FUNC_TRUNC;
286                 } else {
287                         openfn |= OPENX_OPEN_FUNC_OPEN;
288                 }
289         }
290
291         accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
292
293         if ((flags & O_ACCMODE) == O_RDWR) {
294                 accessmode |= OPENX_MODE_ACCESS_RDWR;
295         } else if ((flags & O_ACCMODE) == O_WRONLY) {
296                 accessmode |= OPENX_MODE_ACCESS_WRITE;
297         } 
298
299 #if defined(O_SYNC)
300         if ((flags & O_SYNC) == O_SYNC) {
301                 accessmode |= OPENX_MODE_WRITE_THRU;
302         }
303 #endif
304
305         if (share_mode == DENY_FCB) {
306                 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
307         }
308
309         open_parms.openx.level = RAW_OPEN_OPENX;
310         open_parms.openx.in.flags = 0;
311         open_parms.openx.in.open_mode = accessmode;
312         open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
313         open_parms.openx.in.file_attrs = 0;
314         open_parms.openx.in.write_time = 0;
315         open_parms.openx.in.open_func = openfn;
316         open_parms.openx.in.size = 0;
317         open_parms.openx.in.timeout = 0;
318         open_parms.openx.in.fname = fname;
319
320         status = smb_raw_open(tree, mem_ctx, &open_parms);
321         talloc_destroy(mem_ctx);
322
323         if (NT_STATUS_IS_OK(status)) {
324                 return open_parms.openx.out.fnum;
325         }
326
327         return -1;
328 }
329
330
331 /****************************************************************************
332  Close a file.
333 ****************************************************************************/
334 NTSTATUS smbcli_close(struct smbcli_tree *tree, int fnum)
335 {
336         union smb_close close_parms;
337         NTSTATUS status;
338
339         close_parms.close.level = RAW_CLOSE_CLOSE;
340         close_parms.close.in.fnum = fnum;
341         close_parms.close.in.write_time = 0;
342         status = smb_raw_close(tree, &close_parms);
343         return status;
344 }
345
346 /****************************************************************************
347  send a lock with a specified locktype 
348  this is used for testing LOCKING_ANDX_CANCEL_LOCK
349 ****************************************************************************/
350 NTSTATUS smbcli_locktype(struct smbcli_tree *tree, int fnum, 
351                       uint32_t offset, uint32_t len, int timeout, 
352                       uint8_t locktype)
353 {
354         union smb_lock parms;
355         struct smb_lock_entry lock[1];
356         NTSTATUS status;
357
358         parms.lockx.level = RAW_LOCK_LOCKX;
359         parms.lockx.in.fnum = fnum;
360         parms.lockx.in.mode = locktype;
361         parms.lockx.in.timeout = timeout;
362         parms.lockx.in.ulock_cnt = 0;
363         parms.lockx.in.lock_cnt = 1;
364         lock[0].pid = tree->session->pid;
365         lock[0].offset = offset;
366         lock[0].count = len;
367         parms.lockx.in.locks = &lock[0];
368
369         status = smb_raw_lock(tree, &parms);
370         
371         return status;
372 }
373
374
375 /****************************************************************************
376  Lock a file.
377 ****************************************************************************/
378 NTSTATUS smbcli_lock(struct smbcli_tree *tree, int fnum, 
379                   uint32_t offset, uint32_t len, int timeout, 
380                   enum brl_type lock_type)
381 {
382         union smb_lock parms;
383         struct smb_lock_entry lock[1];
384         NTSTATUS status;
385
386         parms.lockx.level = RAW_LOCK_LOCKX;
387         parms.lockx.in.fnum = fnum;
388         parms.lockx.in.mode = (lock_type == READ_LOCK? 1 : 0);
389         parms.lockx.in.timeout = timeout;
390         parms.lockx.in.ulock_cnt = 0;
391         parms.lockx.in.lock_cnt = 1;
392         lock[0].pid = tree->session->pid;
393         lock[0].offset = offset;
394         lock[0].count = len;
395         parms.lockx.in.locks = &lock[0];
396
397         status = smb_raw_lock(tree, &parms);
398
399         return status;
400 }
401
402
403 /****************************************************************************
404  Unlock a file.
405 ****************************************************************************/
406 NTSTATUS smbcli_unlock(struct smbcli_tree *tree, int fnum, uint32_t offset, uint32_t len)
407 {
408         union smb_lock parms;
409         struct smb_lock_entry lock[1];
410         NTSTATUS status;
411
412         parms.lockx.level = RAW_LOCK_LOCKX;
413         parms.lockx.in.fnum = fnum;
414         parms.lockx.in.mode = 0;
415         parms.lockx.in.timeout = 0;
416         parms.lockx.in.ulock_cnt = 1;
417         parms.lockx.in.lock_cnt = 0;
418         lock[0].pid = tree->session->pid;
419         lock[0].offset = offset;
420         lock[0].count = len;
421         parms.lockx.in.locks = &lock[0];
422         
423         status = smb_raw_lock(tree, &parms);
424         return status;
425 }
426         
427
428 /****************************************************************************
429  Lock a file with 64 bit offsets.
430 ****************************************************************************/
431 NTSTATUS smbcli_lock64(struct smbcli_tree *tree, int fnum, 
432                     off_t offset, off_t len, int timeout, 
433                     enum brl_type lock_type)
434 {
435         union smb_lock parms;
436         int ltype;
437         struct smb_lock_entry lock[1];
438         NTSTATUS status;
439
440         if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
441                 return smbcli_lock(tree, fnum, offset, len, timeout, lock_type);
442         }
443
444         parms.lockx.level = RAW_LOCK_LOCKX;
445         parms.lockx.in.fnum = fnum;
446         
447         ltype = (lock_type == READ_LOCK? 1 : 0);
448         ltype |= LOCKING_ANDX_LARGE_FILES;
449         parms.lockx.in.mode = ltype;
450         parms.lockx.in.timeout = timeout;
451         parms.lockx.in.ulock_cnt = 0;
452         parms.lockx.in.lock_cnt = 1;
453         lock[0].pid = tree->session->pid;
454         lock[0].offset = offset;
455         lock[0].count = len;
456         parms.lockx.in.locks = &lock[0];
457
458         status = smb_raw_lock(tree, &parms);
459         
460         return status;
461 }
462
463
464 /****************************************************************************
465  Unlock a file with 64 bit offsets.
466 ****************************************************************************/
467 NTSTATUS smbcli_unlock64(struct smbcli_tree *tree, int fnum, off_t offset, 
468                          off_t len)
469 {
470         union smb_lock parms;
471         struct smb_lock_entry lock[1];
472         NTSTATUS status;
473
474         if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
475                 return smbcli_unlock(tree, fnum, offset, len);
476         }
477
478         parms.lockx.level = RAW_LOCK_LOCKX;
479         parms.lockx.in.fnum = fnum;
480         parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
481         parms.lockx.in.timeout = 0;
482         parms.lockx.in.ulock_cnt = 1;
483         parms.lockx.in.lock_cnt = 0;
484         lock[0].pid = tree->session->pid;
485         lock[0].offset = offset;
486         lock[0].count = len;
487         parms.lockx.in.locks = &lock[0];
488
489         status = smb_raw_lock(tree, &parms);
490
491         return status;
492 }
493
494
495 /****************************************************************************
496  Do a SMBgetattrE call.
497 ****************************************************************************/
498 NTSTATUS smbcli_getattrE(struct smbcli_tree *tree, int fnum,
499                       uint16_t *attr, size_t *size,
500                       time_t *c_time, time_t *a_time, time_t *m_time)
501 {               
502         union smb_fileinfo parms;
503         NTSTATUS status;
504
505         parms.getattre.level = RAW_FILEINFO_GETATTRE;
506         parms.getattre.in.fnum = fnum;
507
508         status = smb_raw_fileinfo(tree, NULL, &parms);
509
510         if (!NT_STATUS_IS_OK(status))
511                 return status;
512
513         if (size) {
514                 *size = parms.getattre.out.size;
515         }
516
517         if (attr) {
518                 *attr = parms.getattre.out.attrib;
519         }
520
521         if (c_time) {
522                 *c_time = parms.getattre.out.create_time;
523         }
524
525         if (a_time) {
526                 *a_time = parms.getattre.out.access_time;
527         }
528
529         if (m_time) {
530                 *m_time = parms.getattre.out.write_time;
531         }
532
533         return status;
534 }
535
536 /****************************************************************************
537  Do a SMBgetatr call
538 ****************************************************************************/
539 NTSTATUS smbcli_getatr(struct smbcli_tree *tree, const char *fname, 
540                     uint16_t *attr, size_t *size, time_t *t)
541 {
542         union smb_fileinfo parms;
543         NTSTATUS status;
544
545         parms.getattr.level = RAW_FILEINFO_GETATTR;
546         parms.getattr.in.fname = fname;
547
548         status = smb_raw_pathinfo(tree, NULL, &parms);
549         
550         if (!NT_STATUS_IS_OK(status)) {
551                 return status;
552         }
553
554         if (size) {
555                 *size = parms.getattr.out.size;
556         }
557
558         if (t) {
559                 *t = parms.getattr.out.write_time;
560         }
561
562         if (attr) {
563                 *attr = parms.getattr.out.attrib;
564         }
565
566         return status;
567 }
568
569
570 /****************************************************************************
571  Do a SMBsetatr call.
572 ****************************************************************************/
573 NTSTATUS smbcli_setatr(struct smbcli_tree *tree, const char *fname, uint16_t mode, 
574                     time_t t)
575 {
576         union smb_setfileinfo parms;
577         NTSTATUS status;
578
579         parms.setattr.level = RAW_SFILEINFO_SETATTR;
580         parms.setattr.in.attrib = mode;
581         parms.setattr.in.write_time = t;
582         parms.setattr.file.fname = fname;
583         
584         status = smb_raw_setpathinfo(tree, &parms);
585
586         return status;
587 }
588
589
590 /****************************************************************************
591  Check for existence of a dir.
592 ****************************************************************************/
593 NTSTATUS smbcli_chkpath(struct smbcli_tree *tree, const char *path)
594 {
595         struct smb_chkpath parms;
596         char *path2;
597         NTSTATUS status;
598
599         path2 = strdup(path);
600         trim_string(path2,NULL,"\\");
601         if (!*path2) {
602                 free(path2);
603                 path2 = strdup("\\");
604         }
605
606         parms.in.path = path2;
607         
608         status = smb_raw_chkpath(tree, &parms);
609
610         free(path2);
611
612         return status;
613 }
614
615
616 /****************************************************************************
617  Query disk space.
618 ****************************************************************************/
619 NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, int *bsize, int *total, int *avail)
620 {
621         union smb_fsinfo fsinfo_parms;
622         TALLOC_CTX *mem_ctx;
623         NTSTATUS status;
624
625         mem_ctx = talloc_init("smbcli_dskattr");
626
627         fsinfo_parms.dskattr.level = RAW_QFS_DSKATTR;
628         status = smb_raw_fsinfo(tree, mem_ctx, &fsinfo_parms);
629         if (NT_STATUS_IS_OK(status)) {
630                 *bsize = fsinfo_parms.dskattr.out.block_size;
631                 *total = fsinfo_parms.dskattr.out.units_total;
632                 *avail = fsinfo_parms.dskattr.out.units_free;
633         }
634
635         talloc_destroy(mem_ctx);
636         
637         return status;
638 }
639
640
641 /****************************************************************************
642  Create and open a temporary file.
643 ****************************************************************************/
644 int smbcli_ctemp(struct smbcli_tree *tree, const char *path, char **tmp_path)
645 {
646         union smb_open open_parms;
647         TALLOC_CTX *mem_ctx;
648         NTSTATUS status;
649
650         mem_ctx = talloc_init("raw_open");
651         if (!mem_ctx) return -1;
652
653         open_parms.openx.level = RAW_OPEN_CTEMP;
654         open_parms.ctemp.in.attrib = 0;
655         open_parms.ctemp.in.directory = path;
656         open_parms.ctemp.in.write_time = 0;
657
658         status = smb_raw_open(tree, mem_ctx, &open_parms);
659         if (tmp_path) {
660                 *tmp_path = strdup(open_parms.ctemp.out.name);
661         }
662         talloc_destroy(mem_ctx);
663         if (NT_STATUS_IS_OK(status)) {
664                 return open_parms.ctemp.out.fnum;
665         }
666         return -1;
667 }