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