r9022: One more step in the game of whack-a-mole with the PAC.
[Samba/gbeck.git] / source4 / libcli / clifile.c
blob0b9cac4c07c7014fa69b40a346b7198136f47dc0
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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 #include "includes.h"
24 #include "system/filesys.h"
25 #include "libcli/raw/libcliraw.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.file.fname = 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.file.fname = fname_src;
45 parms.unix_link.in.link_dest = fname_dst;
48 status = smb_raw_setpathinfo(tree, &parms);
50 return status;
53 /****************************************************************************
54 Map standard UNIX permissions onto wire representations.
55 ****************************************************************************/
56 uint32_t unix_perms_to_wire(mode_t perms)
58 uint_t ret = 0;
60 ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0);
61 ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0);
62 ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0);
63 ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0);
64 ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0);
65 ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0);
66 ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0);
67 ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0);
68 ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0);
69 #ifdef S_ISVTX
70 ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0);
71 #endif
72 #ifdef S_ISGID
73 ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0);
74 #endif
75 #ifdef S_ISUID
76 ret |= ((perms & S_ISUID) ? UNIX_SET_UID : 0);
77 #endif
78 return ret;
81 /****************************************************************************
82 Symlink a file (UNIX extensions).
83 ****************************************************************************/
84 NTSTATUS smbcli_unix_symlink(struct smbcli_tree *tree, const char *fname_src,
85 const char *fname_dst)
87 return smbcli_link_internal(tree, fname_src, fname_dst, False);
90 /****************************************************************************
91 Hard a file (UNIX extensions).
92 ****************************************************************************/
93 NTSTATUS smbcli_unix_hardlink(struct smbcli_tree *tree, const char *fname_src,
94 const char *fname_dst)
96 return smbcli_link_internal(tree, fname_src, fname_dst, True);
100 /****************************************************************************
101 Chmod or chown a file internal (UNIX extensions).
102 ****************************************************************************/
103 static NTSTATUS smbcli_unix_chmod_chown_internal(struct smbcli_tree *tree,
104 const char *fname,
105 uint32_t mode, uint32_t uid,
106 uint32_t gid)
108 union smb_setfileinfo parms;
109 NTSTATUS status;
111 parms.generic.level = SMB_SFILEINFO_UNIX_BASIC;
112 parms.unix_basic.file.fname = fname;
113 parms.unix_basic.in.uid = uid;
114 parms.unix_basic.in.gid = gid;
115 parms.unix_basic.in.mode = mode;
117 status = smb_raw_setpathinfo(tree, &parms);
119 return status;
122 /****************************************************************************
123 chmod a file (UNIX extensions).
124 ****************************************************************************/
126 NTSTATUS smbcli_unix_chmod(struct smbcli_tree *tree, const char *fname, mode_t mode)
128 return smbcli_unix_chmod_chown_internal(tree, fname,
129 unix_perms_to_wire(mode),
130 SMB_UID_NO_CHANGE,
131 SMB_GID_NO_CHANGE);
134 /****************************************************************************
135 chown a file (UNIX extensions).
136 ****************************************************************************/
137 NTSTATUS smbcli_unix_chown(struct smbcli_tree *tree, const char *fname, uid_t uid,
138 gid_t gid)
140 return smbcli_unix_chmod_chown_internal(tree, fname, SMB_MODE_NO_CHANGE,
141 (uint32_t)uid, (uint32_t)gid);
145 /****************************************************************************
146 Rename a file.
147 ****************************************************************************/
148 NTSTATUS smbcli_rename(struct smbcli_tree *tree, const char *fname_src,
149 const char *fname_dst)
151 union smb_rename parms;
153 parms.generic.level = RAW_RENAME_RENAME;
154 parms.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
155 parms.rename.in.pattern1 = fname_src;
156 parms.rename.in.pattern2 = fname_dst;
158 return smb_raw_rename(tree, &parms);
162 /****************************************************************************
163 Delete a file.
164 ****************************************************************************/
165 NTSTATUS smbcli_unlink(struct smbcli_tree *tree, const char *fname)
167 struct smb_unlink parms;
169 parms.in.pattern = fname;
170 if (strchr(fname, '*')) {
171 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
172 } else {
173 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
176 return smb_raw_unlink(tree, &parms);
179 /****************************************************************************
180 Create a directory.
181 ****************************************************************************/
182 NTSTATUS smbcli_mkdir(struct smbcli_tree *tree, const char *dname)
184 union smb_mkdir parms;
186 parms.mkdir.level = RAW_MKDIR_MKDIR;
187 parms.mkdir.in.path = dname;
189 return smb_raw_mkdir(tree, &parms);
193 /****************************************************************************
194 Remove a directory.
195 ****************************************************************************/
196 NTSTATUS smbcli_rmdir(struct smbcli_tree *tree, const char *dname)
198 struct smb_rmdir parms;
200 parms.in.path = dname;
202 return smb_raw_rmdir(tree, &parms);
206 /****************************************************************************
207 Set or clear the delete on close flag.
208 ****************************************************************************/
209 NTSTATUS smbcli_nt_delete_on_close(struct smbcli_tree *tree, int fnum, BOOL flag)
211 union smb_setfileinfo parms;
212 NTSTATUS status;
214 parms.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
215 parms.disposition_info.file.fnum = fnum;
216 parms.disposition_info.in.delete_on_close = flag;
218 status = smb_raw_setfileinfo(tree, &parms);
220 return status;
224 /****************************************************************************
225 Create/open a file - exposing the full horror of the NT API :-).
226 Used in CIFS-on-CIFS NTVFS.
227 ****************************************************************************/
228 int smbcli_nt_create_full(struct smbcli_tree *tree, const char *fname,
229 uint32_t CreatFlags, uint32_t DesiredAccess,
230 uint32_t FileAttributes, uint32_t ShareAccess,
231 uint32_t CreateDisposition, uint32_t CreateOptions,
232 uint8_t SecurityFlags)
234 union smb_open open_parms;
235 TALLOC_CTX *mem_ctx;
236 NTSTATUS status;
238 mem_ctx = talloc_init("raw_open");
239 if (!mem_ctx) return -1;
241 open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
242 open_parms.ntcreatex.in.flags = CreatFlags;
243 open_parms.ntcreatex.in.root_fid = 0;
244 open_parms.ntcreatex.in.access_mask = DesiredAccess;
245 open_parms.ntcreatex.in.file_attr = FileAttributes;
246 open_parms.ntcreatex.in.alloc_size = 0;
247 open_parms.ntcreatex.in.share_access = ShareAccess;
248 open_parms.ntcreatex.in.open_disposition = CreateDisposition;
249 open_parms.ntcreatex.in.create_options = CreateOptions;
250 open_parms.ntcreatex.in.impersonation = 0;
251 open_parms.ntcreatex.in.security_flags = SecurityFlags;
252 open_parms.ntcreatex.in.fname = fname;
254 status = smb_raw_open(tree, mem_ctx, &open_parms);
255 talloc_free(mem_ctx);
257 if (NT_STATUS_IS_OK(status)) {
258 return open_parms.ntcreatex.out.fnum;
261 return -1;
265 /****************************************************************************
266 Open a file (using SMBopenx)
267 WARNING: if you open with O_WRONLY then getattrE won't work!
268 ****************************************************************************/
269 int smbcli_open(struct smbcli_tree *tree, const char *fname, int flags,
270 int share_mode)
272 union smb_open open_parms;
273 uint_t openfn=0;
274 uint_t accessmode=0;
275 TALLOC_CTX *mem_ctx;
276 NTSTATUS status;
278 mem_ctx = talloc_init("raw_open");
279 if (!mem_ctx) return -1;
281 if (flags & O_CREAT) {
282 openfn |= OPENX_OPEN_FUNC_CREATE;
284 if (!(flags & O_EXCL)) {
285 if (flags & O_TRUNC) {
286 openfn |= OPENX_OPEN_FUNC_TRUNC;
287 } else {
288 openfn |= OPENX_OPEN_FUNC_OPEN;
292 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
294 if ((flags & O_ACCMODE) == O_RDWR) {
295 accessmode |= OPENX_MODE_ACCESS_RDWR;
296 } else if ((flags & O_ACCMODE) == O_WRONLY) {
297 accessmode |= OPENX_MODE_ACCESS_WRITE;
300 #if defined(O_SYNC)
301 if ((flags & O_SYNC) == O_SYNC) {
302 accessmode |= OPENX_MODE_WRITE_THRU;
304 #endif
306 if (share_mode == DENY_FCB) {
307 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
310 open_parms.openx.level = RAW_OPEN_OPENX;
311 open_parms.openx.in.flags = 0;
312 open_parms.openx.in.open_mode = accessmode;
313 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
314 open_parms.openx.in.file_attrs = 0;
315 open_parms.openx.in.write_time = 0;
316 open_parms.openx.in.open_func = openfn;
317 open_parms.openx.in.size = 0;
318 open_parms.openx.in.timeout = 0;
319 open_parms.openx.in.fname = fname;
321 status = smb_raw_open(tree, mem_ctx, &open_parms);
322 talloc_free(mem_ctx);
324 if (NT_STATUS_IS_OK(status)) {
325 return open_parms.openx.out.fnum;
328 return -1;
332 /****************************************************************************
333 Close a file.
334 ****************************************************************************/
335 NTSTATUS smbcli_close(struct smbcli_tree *tree, int fnum)
337 union smb_close close_parms;
338 NTSTATUS status;
340 close_parms.close.level = RAW_CLOSE_CLOSE;
341 close_parms.close.in.fnum = fnum;
342 close_parms.close.in.write_time = 0;
343 status = smb_raw_close(tree, &close_parms);
344 return status;
347 /****************************************************************************
348 send a lock with a specified locktype
349 this is used for testing LOCKING_ANDX_CANCEL_LOCK
350 ****************************************************************************/
351 NTSTATUS smbcli_locktype(struct smbcli_tree *tree, int fnum,
352 uint32_t offset, uint32_t len, int timeout,
353 uint8_t locktype)
355 union smb_lock parms;
356 struct smb_lock_entry lock[1];
357 NTSTATUS status;
359 parms.lockx.level = RAW_LOCK_LOCKX;
360 parms.lockx.in.fnum = fnum;
361 parms.lockx.in.mode = locktype;
362 parms.lockx.in.timeout = timeout;
363 parms.lockx.in.ulock_cnt = 0;
364 parms.lockx.in.lock_cnt = 1;
365 lock[0].pid = tree->session->pid;
366 lock[0].offset = offset;
367 lock[0].count = len;
368 parms.lockx.in.locks = &lock[0];
370 status = smb_raw_lock(tree, &parms);
372 return status;
376 /****************************************************************************
377 Lock a file.
378 ****************************************************************************/
379 NTSTATUS smbcli_lock(struct smbcli_tree *tree, int fnum,
380 uint32_t offset, uint32_t len, int timeout,
381 enum brl_type lock_type)
383 union smb_lock parms;
384 struct smb_lock_entry lock[1];
385 NTSTATUS status;
387 parms.lockx.level = RAW_LOCK_LOCKX;
388 parms.lockx.in.fnum = fnum;
389 parms.lockx.in.mode = (lock_type == READ_LOCK? 1 : 0);
390 parms.lockx.in.timeout = timeout;
391 parms.lockx.in.ulock_cnt = 0;
392 parms.lockx.in.lock_cnt = 1;
393 lock[0].pid = tree->session->pid;
394 lock[0].offset = offset;
395 lock[0].count = len;
396 parms.lockx.in.locks = &lock[0];
398 status = smb_raw_lock(tree, &parms);
400 return status;
404 /****************************************************************************
405 Unlock a file.
406 ****************************************************************************/
407 NTSTATUS smbcli_unlock(struct smbcli_tree *tree, int fnum, uint32_t offset, uint32_t len)
409 union smb_lock parms;
410 struct smb_lock_entry lock[1];
411 NTSTATUS status;
413 parms.lockx.level = RAW_LOCK_LOCKX;
414 parms.lockx.in.fnum = fnum;
415 parms.lockx.in.mode = 0;
416 parms.lockx.in.timeout = 0;
417 parms.lockx.in.ulock_cnt = 1;
418 parms.lockx.in.lock_cnt = 0;
419 lock[0].pid = tree->session->pid;
420 lock[0].offset = offset;
421 lock[0].count = len;
422 parms.lockx.in.locks = &lock[0];
424 status = smb_raw_lock(tree, &parms);
425 return status;
429 /****************************************************************************
430 Lock a file with 64 bit offsets.
431 ****************************************************************************/
432 NTSTATUS smbcli_lock64(struct smbcli_tree *tree, int fnum,
433 off_t offset, off_t len, int timeout,
434 enum brl_type lock_type)
436 union smb_lock parms;
437 int ltype;
438 struct smb_lock_entry lock[1];
439 NTSTATUS status;
441 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
442 return smbcli_lock(tree, fnum, offset, len, timeout, lock_type);
445 parms.lockx.level = RAW_LOCK_LOCKX;
446 parms.lockx.in.fnum = fnum;
448 ltype = (lock_type == READ_LOCK? 1 : 0);
449 ltype |= LOCKING_ANDX_LARGE_FILES;
450 parms.lockx.in.mode = ltype;
451 parms.lockx.in.timeout = timeout;
452 parms.lockx.in.ulock_cnt = 0;
453 parms.lockx.in.lock_cnt = 1;
454 lock[0].pid = tree->session->pid;
455 lock[0].offset = offset;
456 lock[0].count = len;
457 parms.lockx.in.locks = &lock[0];
459 status = smb_raw_lock(tree, &parms);
461 return status;
465 /****************************************************************************
466 Unlock a file with 64 bit offsets.
467 ****************************************************************************/
468 NTSTATUS smbcli_unlock64(struct smbcli_tree *tree, int fnum, off_t offset,
469 off_t len)
471 union smb_lock parms;
472 struct smb_lock_entry lock[1];
473 NTSTATUS status;
475 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
476 return smbcli_unlock(tree, fnum, offset, len);
479 parms.lockx.level = RAW_LOCK_LOCKX;
480 parms.lockx.in.fnum = fnum;
481 parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
482 parms.lockx.in.timeout = 0;
483 parms.lockx.in.ulock_cnt = 1;
484 parms.lockx.in.lock_cnt = 0;
485 lock[0].pid = tree->session->pid;
486 lock[0].offset = offset;
487 lock[0].count = len;
488 parms.lockx.in.locks = &lock[0];
490 status = smb_raw_lock(tree, &parms);
492 return status;
496 /****************************************************************************
497 Do a SMBgetattrE call.
498 ****************************************************************************/
499 NTSTATUS smbcli_getattrE(struct smbcli_tree *tree, int fnum,
500 uint16_t *attr, size_t *size,
501 time_t *c_time, time_t *a_time, time_t *m_time)
503 union smb_fileinfo parms;
504 NTSTATUS status;
506 parms.getattre.level = RAW_FILEINFO_GETATTRE;
507 parms.getattre.in.fnum = fnum;
509 status = smb_raw_fileinfo(tree, NULL, &parms);
511 if (!NT_STATUS_IS_OK(status))
512 return status;
514 if (size) {
515 *size = parms.getattre.out.size;
518 if (attr) {
519 *attr = parms.getattre.out.attrib;
522 if (c_time) {
523 *c_time = parms.getattre.out.create_time;
526 if (a_time) {
527 *a_time = parms.getattre.out.access_time;
530 if (m_time) {
531 *m_time = parms.getattre.out.write_time;
534 return status;
537 /****************************************************************************
538 Do a SMBgetatr call
539 ****************************************************************************/
540 NTSTATUS smbcli_getatr(struct smbcli_tree *tree, const char *fname,
541 uint16_t *attr, size_t *size, time_t *t)
543 union smb_fileinfo parms;
544 NTSTATUS status;
546 parms.getattr.level = RAW_FILEINFO_GETATTR;
547 parms.getattr.in.fname = fname;
549 status = smb_raw_pathinfo(tree, NULL, &parms);
551 if (!NT_STATUS_IS_OK(status)) {
552 return status;
555 if (size) {
556 *size = parms.getattr.out.size;
559 if (t) {
560 *t = parms.getattr.out.write_time;
563 if (attr) {
564 *attr = parms.getattr.out.attrib;
567 return status;
571 /****************************************************************************
572 Do a SMBsetatr call.
573 ****************************************************************************/
574 NTSTATUS smbcli_setatr(struct smbcli_tree *tree, const char *fname, uint16_t mode,
575 time_t t)
577 union smb_setfileinfo parms;
578 NTSTATUS status;
580 parms.setattr.level = RAW_SFILEINFO_SETATTR;
581 parms.setattr.in.attrib = mode;
582 parms.setattr.in.write_time = t;
583 parms.setattr.file.fname = fname;
585 status = smb_raw_setpathinfo(tree, &parms);
587 return status;
591 /****************************************************************************
592 Check for existence of a dir.
593 ****************************************************************************/
594 NTSTATUS smbcli_chkpath(struct smbcli_tree *tree, const char *path)
596 struct smb_chkpath parms;
597 char *path2;
598 NTSTATUS status;
600 path2 = strdup(path);
601 trim_string(path2,NULL,"\\");
602 if (!*path2) {
603 free(path2);
604 path2 = strdup("\\");
607 parms.in.path = path2;
609 status = smb_raw_chkpath(tree, &parms);
611 free(path2);
613 return status;
617 /****************************************************************************
618 Query disk space.
619 ****************************************************************************/
620 NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, int *bsize, int *total, int *avail)
622 union smb_fsinfo fsinfo_parms;
623 TALLOC_CTX *mem_ctx;
624 NTSTATUS status;
626 mem_ctx = talloc_init("smbcli_dskattr");
628 fsinfo_parms.dskattr.level = RAW_QFS_DSKATTR;
629 status = smb_raw_fsinfo(tree, mem_ctx, &fsinfo_parms);
630 if (NT_STATUS_IS_OK(status)) {
631 *bsize = fsinfo_parms.dskattr.out.block_size;
632 *total = fsinfo_parms.dskattr.out.units_total;
633 *avail = fsinfo_parms.dskattr.out.units_free;
636 talloc_free(mem_ctx);
638 return status;
642 /****************************************************************************
643 Create and open a temporary file.
644 ****************************************************************************/
645 int smbcli_ctemp(struct smbcli_tree *tree, const char *path, char **tmp_path)
647 union smb_open open_parms;
648 TALLOC_CTX *mem_ctx;
649 NTSTATUS status;
651 mem_ctx = talloc_init("raw_open");
652 if (!mem_ctx) return -1;
654 open_parms.openx.level = RAW_OPEN_CTEMP;
655 open_parms.ctemp.in.attrib = 0;
656 open_parms.ctemp.in.directory = path;
657 open_parms.ctemp.in.write_time = 0;
659 status = smb_raw_open(tree, mem_ctx, &open_parms);
660 if (tmp_path) {
661 *tmp_path = strdup(open_parms.ctemp.out.name);
663 talloc_free(mem_ctx);
664 if (NT_STATUS_IS_OK(status)) {
665 return open_parms.ctemp.out.fnum;
667 return -1;