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