source4/libcli: Only set ctemp set on success
[Samba/vl.git] / source4 / libcli / clifile.c
blob19288247c4467351f01e3a729b86460a87c17d55
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
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 3 of the License, or
11 (at your option) any later version.
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.
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 #include "includes.h"
23 #include "system/filesys.h"
24 #include "libcli/raw/libcliraw.h"
25 #include "libcli/libcli.h"
27 /****************************************************************************
28 Hard/Symlink a file (UNIX extensions).
29 ****************************************************************************/
31 static NTSTATUS smbcli_link_internal(struct smbcli_tree *tree,
32 const char *fname_src,
33 const char *fname_dst, bool hard_link)
35 union smb_setfileinfo parms;
36 NTSTATUS status;
38 if (hard_link) {
39 parms.generic.level = RAW_SFILEINFO_UNIX_HLINK;
40 parms.unix_hlink.in.file.path = fname_src;
41 parms.unix_hlink.in.link_dest = fname_dst;
42 } else {
43 parms.generic.level = RAW_SFILEINFO_UNIX_LINK;
44 parms.unix_link.in.file.path = fname_src;
45 parms.unix_link.in.link_dest = fname_dst;
48 status = smb_raw_setpathinfo(tree, &parms);
50 return status;
53 /****************************************************************************
54 Symlink a file (UNIX extensions).
55 ****************************************************************************/
56 NTSTATUS smbcli_unix_symlink(struct smbcli_tree *tree, const char *fname_src,
57 const char *fname_dst)
59 return smbcli_link_internal(tree, fname_src, fname_dst, false);
62 /****************************************************************************
63 Hard a file (UNIX extensions).
64 ****************************************************************************/
65 NTSTATUS smbcli_unix_hardlink(struct smbcli_tree *tree, const char *fname_src,
66 const char *fname_dst)
68 return smbcli_link_internal(tree, fname_src, fname_dst, true);
72 /****************************************************************************
73 Chmod or chown a file internal (UNIX extensions).
74 ****************************************************************************/
75 static NTSTATUS smbcli_unix_chmod_chown_internal(struct smbcli_tree *tree,
76 const char *fname,
77 uint32_t mode, uint32_t uid,
78 uint32_t gid)
80 union smb_setfileinfo parms;
81 NTSTATUS status;
83 parms.generic.level = SMB_SFILEINFO_UNIX_BASIC;
84 parms.unix_basic.in.file.path = fname;
85 parms.unix_basic.in.uid = uid;
86 parms.unix_basic.in.gid = gid;
87 parms.unix_basic.in.mode = mode;
89 status = smb_raw_setpathinfo(tree, &parms);
91 return status;
94 /****************************************************************************
95 chmod a file (UNIX extensions).
96 ****************************************************************************/
98 NTSTATUS smbcli_unix_chmod(struct smbcli_tree *tree, const char *fname, mode_t mode)
100 return smbcli_unix_chmod_chown_internal(tree, fname,
101 unix_perms_to_wire(mode),
102 SMB_UID_NO_CHANGE,
103 SMB_GID_NO_CHANGE);
106 /****************************************************************************
107 chown a file (UNIX extensions).
108 ****************************************************************************/
109 NTSTATUS smbcli_unix_chown(struct smbcli_tree *tree, const char *fname, uid_t uid,
110 gid_t gid)
112 return smbcli_unix_chmod_chown_internal(tree, fname, SMB_MODE_NO_CHANGE,
113 (uint32_t)uid, (uint32_t)gid);
117 /****************************************************************************
118 Rename a file.
119 ****************************************************************************/
120 NTSTATUS smbcli_rename(struct smbcli_tree *tree, const char *fname_src,
121 const char *fname_dst)
123 union smb_rename parms;
125 parms.generic.level = RAW_RENAME_RENAME;
126 parms.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
127 parms.rename.in.pattern1 = fname_src;
128 parms.rename.in.pattern2 = fname_dst;
130 return smb_raw_rename(tree, &parms);
134 /****************************************************************************
135 Delete a file.
136 ****************************************************************************/
137 NTSTATUS smbcli_unlink(struct smbcli_tree *tree, const char *fname)
139 union smb_unlink parms;
141 parms.unlink.in.pattern = fname;
142 if (strchr(fname, '*')) {
143 parms.unlink.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
144 } else {
145 parms.unlink.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
148 return smb_raw_unlink(tree, &parms);
151 /****************************************************************************
152 Create a directory.
153 ****************************************************************************/
154 NTSTATUS smbcli_mkdir(struct smbcli_tree *tree, const char *dname)
156 union smb_mkdir parms;
158 parms.mkdir.level = RAW_MKDIR_MKDIR;
159 parms.mkdir.in.path = dname;
161 return smb_raw_mkdir(tree, &parms);
165 /****************************************************************************
166 Remove a directory.
167 ****************************************************************************/
168 NTSTATUS smbcli_rmdir(struct smbcli_tree *tree, const char *dname)
170 struct smb_rmdir parms;
172 parms.in.path = dname;
174 return smb_raw_rmdir(tree, &parms);
178 /****************************************************************************
179 Set or clear the delete on close flag.
180 ****************************************************************************/
181 NTSTATUS smbcli_nt_delete_on_close(struct smbcli_tree *tree, int fnum,
182 bool flag)
184 union smb_setfileinfo parms;
185 NTSTATUS status;
187 parms.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
188 parms.disposition_info.in.file.fnum = fnum;
189 parms.disposition_info.in.delete_on_close = flag;
191 status = smb_raw_setfileinfo(tree, &parms);
193 return status;
197 /****************************************************************************
198 Create/open a file - exposing the full horror of the NT API :-).
199 Used in CIFS-on-CIFS NTVFS.
200 ****************************************************************************/
201 int smbcli_nt_create_full(struct smbcli_tree *tree, const char *fname,
202 uint32_t CreatFlags, uint32_t DesiredAccess,
203 uint32_t FileAttributes, uint32_t ShareAccess,
204 uint32_t CreateDisposition, uint32_t CreateOptions,
205 uint8_t SecurityFlags)
207 union smb_open open_parms;
208 TALLOC_CTX *mem_ctx;
209 NTSTATUS status;
211 mem_ctx = talloc_init("raw_open");
212 if (!mem_ctx) return -1;
214 open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
215 open_parms.ntcreatex.in.flags = CreatFlags;
216 open_parms.ntcreatex.in.root_fid.fnum = 0;
217 open_parms.ntcreatex.in.access_mask = DesiredAccess;
218 open_parms.ntcreatex.in.file_attr = FileAttributes;
219 open_parms.ntcreatex.in.alloc_size = 0;
220 open_parms.ntcreatex.in.share_access = ShareAccess;
221 open_parms.ntcreatex.in.open_disposition = CreateDisposition;
222 open_parms.ntcreatex.in.create_options = CreateOptions;
223 open_parms.ntcreatex.in.impersonation = 0;
224 open_parms.ntcreatex.in.security_flags = SecurityFlags;
225 open_parms.ntcreatex.in.fname = fname;
227 status = smb_raw_open(tree, mem_ctx, &open_parms);
228 talloc_free(mem_ctx);
230 if (NT_STATUS_IS_OK(status)) {
231 return open_parms.ntcreatex.out.file.fnum;
234 return -1;
238 /****************************************************************************
239 Open a file (using SMBopenx)
240 WARNING: if you open with O_WRONLY then getattrE won't work!
241 ****************************************************************************/
242 int smbcli_open(struct smbcli_tree *tree, const char *fname, int flags,
243 int share_mode)
245 union smb_open open_parms;
246 unsigned int openfn=0;
247 unsigned int accessmode=0;
248 TALLOC_CTX *mem_ctx;
249 NTSTATUS status;
251 mem_ctx = talloc_init("raw_open");
252 if (!mem_ctx) return -1;
254 if (flags & O_CREAT) {
255 openfn |= OPENX_OPEN_FUNC_CREATE;
257 if (!(flags & O_EXCL)) {
258 if (flags & O_TRUNC) {
259 openfn |= OPENX_OPEN_FUNC_TRUNC;
260 } else {
261 openfn |= OPENX_OPEN_FUNC_OPEN;
265 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
267 if ((flags & O_ACCMODE) == O_RDWR) {
268 accessmode |= OPENX_MODE_ACCESS_RDWR;
269 } else if ((flags & O_ACCMODE) == O_WRONLY) {
270 accessmode |= OPENX_MODE_ACCESS_WRITE;
273 #if defined(O_SYNC)
274 if ((flags & O_SYNC) == O_SYNC) {
275 accessmode |= OPENX_MODE_WRITE_THRU;
277 #endif
279 if (share_mode == DENY_FCB) {
280 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
283 open_parms.openx.level = RAW_OPEN_OPENX;
284 open_parms.openx.in.flags = 0;
285 open_parms.openx.in.open_mode = accessmode;
286 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
287 open_parms.openx.in.file_attrs = 0;
288 open_parms.openx.in.write_time = 0;
289 open_parms.openx.in.open_func = openfn;
290 open_parms.openx.in.size = 0;
291 open_parms.openx.in.timeout = 0;
292 open_parms.openx.in.fname = fname;
294 status = smb_raw_open(tree, mem_ctx, &open_parms);
295 talloc_free(mem_ctx);
297 if (NT_STATUS_IS_OK(status)) {
298 return open_parms.openx.out.file.fnum;
301 return -1;
305 /****************************************************************************
306 Close a file.
307 ****************************************************************************/
308 NTSTATUS smbcli_close(struct smbcli_tree *tree, int fnum)
310 union smb_close close_parms;
311 NTSTATUS status;
313 close_parms.close.level = RAW_CLOSE_CLOSE;
314 close_parms.close.in.file.fnum = fnum;
315 close_parms.close.in.write_time = 0;
316 status = smb_raw_close(tree, &close_parms);
317 return status;
320 /****************************************************************************
321 send a lock with a specified locktype
322 this is used for testing LOCKING_ANDX_CANCEL_LOCK
323 ****************************************************************************/
324 NTSTATUS smbcli_locktype(struct smbcli_tree *tree, int fnum,
325 uint32_t offset, uint32_t len, int timeout,
326 uint8_t locktype)
328 union smb_lock parms;
329 struct smb_lock_entry lock[1];
330 NTSTATUS status;
332 parms.lockx.level = RAW_LOCK_LOCKX;
333 parms.lockx.in.file.fnum = fnum;
334 parms.lockx.in.mode = locktype;
335 parms.lockx.in.timeout = timeout;
336 parms.lockx.in.ulock_cnt = 0;
337 parms.lockx.in.lock_cnt = 1;
338 lock[0].pid = tree->session->pid;
339 lock[0].offset = offset;
340 lock[0].count = len;
341 parms.lockx.in.locks = &lock[0];
343 status = smb_raw_lock(tree, &parms);
345 return status;
349 /****************************************************************************
350 Lock a file.
351 ****************************************************************************/
352 NTSTATUS smbcli_lock(struct smbcli_tree *tree, int fnum,
353 uint32_t offset, uint32_t len, int timeout,
354 enum brl_type lock_type)
356 union smb_lock parms;
357 struct smb_lock_entry lock[1];
358 NTSTATUS status;
360 parms.lockx.level = RAW_LOCK_LOCKX;
361 parms.lockx.in.file.fnum = fnum;
362 parms.lockx.in.mode = (lock_type == READ_LOCK? 1 : 0);
363 parms.lockx.in.timeout = timeout;
364 parms.lockx.in.ulock_cnt = 0;
365 parms.lockx.in.lock_cnt = 1;
366 lock[0].pid = tree->session->pid;
367 lock[0].offset = offset;
368 lock[0].count = len;
369 parms.lockx.in.locks = &lock[0];
371 status = smb_raw_lock(tree, &parms);
373 return status;
377 /****************************************************************************
378 Unlock a file.
379 ****************************************************************************/
380 NTSTATUS smbcli_unlock(struct smbcli_tree *tree, int fnum, uint32_t offset, uint32_t len)
382 union smb_lock parms;
383 struct smb_lock_entry lock[1];
384 NTSTATUS status;
386 parms.lockx.level = RAW_LOCK_LOCKX;
387 parms.lockx.in.file.fnum = fnum;
388 parms.lockx.in.mode = 0;
389 parms.lockx.in.timeout = 0;
390 parms.lockx.in.ulock_cnt = 1;
391 parms.lockx.in.lock_cnt = 0;
392 lock[0].pid = tree->session->pid;
393 lock[0].offset = offset;
394 lock[0].count = len;
395 parms.lockx.in.locks = &lock[0];
397 status = smb_raw_lock(tree, &parms);
398 return status;
402 /****************************************************************************
403 Lock a file with 64 bit offsets.
404 ****************************************************************************/
405 NTSTATUS smbcli_lock64(struct smbcli_tree *tree, int fnum,
406 off_t offset, off_t len, int timeout,
407 enum brl_type lock_type)
409 union smb_lock parms;
410 int ltype;
411 struct smb_lock_entry lock[1];
412 NTSTATUS status;
414 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
415 return smbcli_lock(tree, fnum, offset, len, timeout, lock_type);
418 parms.lockx.level = RAW_LOCK_LOCKX;
419 parms.lockx.in.file.fnum = fnum;
421 ltype = (lock_type == READ_LOCK? 1 : 0);
422 ltype |= LOCKING_ANDX_LARGE_FILES;
423 parms.lockx.in.mode = ltype;
424 parms.lockx.in.timeout = timeout;
425 parms.lockx.in.ulock_cnt = 0;
426 parms.lockx.in.lock_cnt = 1;
427 lock[0].pid = tree->session->pid;
428 lock[0].offset = offset;
429 lock[0].count = len;
430 parms.lockx.in.locks = &lock[0];
432 status = smb_raw_lock(tree, &parms);
434 return status;
438 /****************************************************************************
439 Unlock a file with 64 bit offsets.
440 ****************************************************************************/
441 NTSTATUS smbcli_unlock64(struct smbcli_tree *tree, int fnum, off_t offset,
442 off_t len)
444 union smb_lock parms;
445 struct smb_lock_entry lock[1];
446 NTSTATUS status;
448 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
449 return smbcli_unlock(tree, fnum, offset, len);
452 parms.lockx.level = RAW_LOCK_LOCKX;
453 parms.lockx.in.file.fnum = fnum;
454 parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
455 parms.lockx.in.timeout = 0;
456 parms.lockx.in.ulock_cnt = 1;
457 parms.lockx.in.lock_cnt = 0;
458 lock[0].pid = tree->session->pid;
459 lock[0].offset = offset;
460 lock[0].count = len;
461 parms.lockx.in.locks = &lock[0];
463 status = smb_raw_lock(tree, &parms);
465 return status;
469 /****************************************************************************
470 Do a SMBgetattrE call.
471 ****************************************************************************/
472 NTSTATUS smbcli_getattrE(struct smbcli_tree *tree, int fnum,
473 uint16_t *attr, size_t *size,
474 time_t *c_time, time_t *a_time, time_t *m_time)
476 union smb_fileinfo parms;
477 NTSTATUS status;
479 parms.getattre.level = RAW_FILEINFO_GETATTRE;
480 parms.getattre.in.file.fnum = fnum;
482 status = smb_raw_fileinfo(tree, NULL, &parms);
484 if (!NT_STATUS_IS_OK(status))
485 return status;
487 if (size) {
488 *size = parms.getattre.out.size;
491 if (attr) {
492 *attr = parms.getattre.out.attrib;
495 if (c_time) {
496 *c_time = parms.getattre.out.create_time;
499 if (a_time) {
500 *a_time = parms.getattre.out.access_time;
503 if (m_time) {
504 *m_time = parms.getattre.out.write_time;
507 return status;
510 /****************************************************************************
511 Do a SMBgetatr call
512 ****************************************************************************/
513 NTSTATUS smbcli_getatr(struct smbcli_tree *tree, const char *fname,
514 uint16_t *attr, size_t *size, time_t *t)
516 union smb_fileinfo parms;
517 NTSTATUS status;
519 parms.getattr.level = RAW_FILEINFO_GETATTR;
520 parms.getattr.in.file.path = fname;
522 status = smb_raw_pathinfo(tree, NULL, &parms);
524 if (!NT_STATUS_IS_OK(status)) {
525 return status;
528 if (size) {
529 *size = parms.getattr.out.size;
532 if (t) {
533 *t = parms.getattr.out.write_time;
536 if (attr) {
537 *attr = parms.getattr.out.attrib;
540 return status;
544 /****************************************************************************
545 Do a SMBsetatr call.
546 ****************************************************************************/
547 NTSTATUS smbcli_setatr(struct smbcli_tree *tree, const char *fname, uint16_t mode,
548 time_t t)
550 union smb_setfileinfo parms;
552 parms.setattr.level = RAW_SFILEINFO_SETATTR;
553 parms.setattr.in.file.path = fname;
554 parms.setattr.in.attrib = mode;
555 parms.setattr.in.write_time = t;
557 return smb_raw_setpathinfo(tree, &parms);
560 /****************************************************************************
561 Do a setfileinfo basic_info call.
562 ****************************************************************************/
563 NTSTATUS smbcli_fsetatr(struct smbcli_tree *tree, int fnum, uint16_t mode,
564 NTTIME create_time, NTTIME access_time,
565 NTTIME write_time, NTTIME change_time)
567 union smb_setfileinfo parms;
569 parms.basic_info.level = RAW_SFILEINFO_BASIC_INFO;
570 parms.basic_info.in.file.fnum = fnum;
571 parms.basic_info.in.attrib = mode;
572 parms.basic_info.in.create_time = create_time;
573 parms.basic_info.in.access_time = access_time;
574 parms.basic_info.in.write_time = write_time;
575 parms.basic_info.in.change_time = change_time;
577 return smb_raw_setfileinfo(tree, &parms);
581 /****************************************************************************
582 truncate a file to a given size
583 ****************************************************************************/
584 NTSTATUS smbcli_ftruncate(struct smbcli_tree *tree, int fnum, uint64_t size)
586 union smb_setfileinfo parms;
588 parms.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFO;
589 parms.end_of_file_info.in.file.fnum = fnum;
590 parms.end_of_file_info.in.size = size;
592 return smb_raw_setfileinfo(tree, &parms);
596 /****************************************************************************
597 Check for existence of a dir.
598 ****************************************************************************/
599 NTSTATUS smbcli_chkpath(struct smbcli_tree *tree, const char *path)
601 union smb_chkpath parms;
602 char *path2;
603 NTSTATUS status;
605 path2 = strdup(path);
606 trim_string(path2,NULL,"\\");
607 if (!*path2) {
608 free(path2);
609 path2 = strdup("\\");
612 parms.chkpath.in.path = path2;
614 status = smb_raw_chkpath(tree, &parms);
616 free(path2);
618 return status;
622 /****************************************************************************
623 Query disk space.
624 ****************************************************************************/
625 NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, uint32_t *bsize,
626 uint64_t *total, uint64_t *avail)
628 union smb_fsinfo fsinfo_parms;
629 TALLOC_CTX *mem_ctx;
630 NTSTATUS status;
632 mem_ctx = talloc_init("smbcli_dskattr");
634 fsinfo_parms.dskattr.level = RAW_QFS_SIZE_INFO;
635 status = smb_raw_fsinfo(tree, mem_ctx, &fsinfo_parms);
636 if (NT_STATUS_IS_OK(status)) {
637 *bsize = fsinfo_parms.size_info.out.bytes_per_sector * fsinfo_parms.size_info.out.sectors_per_unit;
638 *total = fsinfo_parms.size_info.out.total_alloc_units;
639 *avail = fsinfo_parms.size_info.out.avail_alloc_units;
642 talloc_free(mem_ctx);
644 return status;
648 /****************************************************************************
649 Create and open a temporary file.
650 ****************************************************************************/
651 int smbcli_ctemp(struct smbcli_tree *tree, const char *path, char **tmp_path)
653 union smb_open open_parms;
654 TALLOC_CTX *mem_ctx;
655 NTSTATUS status;
656 int ret = -1;
658 mem_ctx = talloc_init("raw_open");
659 if (!mem_ctx) return ret;
661 open_parms.openx.level = RAW_OPEN_CTEMP;
662 open_parms.ctemp.in.attrib = 0;
663 open_parms.ctemp.in.directory = path;
664 open_parms.ctemp.in.write_time = 0;
666 status = smb_raw_open(tree, mem_ctx, &open_parms);
667 if (NT_STATUS_IS_OK(status)) {
668 if (tmp_path) {
669 *tmp_path = strdup(open_parms.ctemp.out.name);
671 ret = open_parms.ctemp.out.file.fnum;
673 talloc_free(mem_ctx);
674 return ret;