2 Unix SMB/CIFS implementation.
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.
24 #include "system/filesys.h"
25 #include "libcli/raw/libcliraw.h"
26 #include "libcli/libcli.h"
28 /****************************************************************************
29 Hard/Symlink a file (UNIX extensions).
30 ****************************************************************************/
32 static NTSTATUS
smbcli_link_internal(struct smbcli_tree
*tree
,
33 const char *fname_src
,
34 const char *fname_dst
, BOOL hard_link
)
36 union smb_setfileinfo parms
;
40 parms
.generic
.level
= RAW_SFILEINFO_UNIX_HLINK
;
41 parms
.unix_hlink
.in
.file
.path
= fname_src
;
42 parms
.unix_hlink
.in
.link_dest
= fname_dst
;
44 parms
.generic
.level
= RAW_SFILEINFO_UNIX_LINK
;
45 parms
.unix_link
.in
.file
.path
= fname_src
;
46 parms
.unix_link
.in
.link_dest
= fname_dst
;
49 status
= smb_raw_setpathinfo(tree
, &parms
);
54 /****************************************************************************
55 Map standard UNIX permissions onto wire representations.
56 ****************************************************************************/
57 uint32_t unix_perms_to_wire(mode_t perms
)
61 ret
|= ((perms
& S_IXOTH
) ? UNIX_X_OTH
: 0);
62 ret
|= ((perms
& S_IWOTH
) ? UNIX_W_OTH
: 0);
63 ret
|= ((perms
& S_IROTH
) ? UNIX_R_OTH
: 0);
64 ret
|= ((perms
& S_IXGRP
) ? UNIX_X_GRP
: 0);
65 ret
|= ((perms
& S_IWGRP
) ? UNIX_W_GRP
: 0);
66 ret
|= ((perms
& S_IRGRP
) ? UNIX_R_GRP
: 0);
67 ret
|= ((perms
& S_IXUSR
) ? UNIX_X_USR
: 0);
68 ret
|= ((perms
& S_IWUSR
) ? UNIX_W_USR
: 0);
69 ret
|= ((perms
& S_IRUSR
) ? UNIX_R_USR
: 0);
71 ret
|= ((perms
& S_ISVTX
) ? UNIX_STICKY
: 0);
74 ret
|= ((perms
& S_ISGID
) ? UNIX_SET_GID
: 0);
77 ret
|= ((perms
& S_ISUID
) ? UNIX_SET_UID
: 0);
82 /****************************************************************************
83 Symlink a file (UNIX extensions).
84 ****************************************************************************/
85 NTSTATUS
smbcli_unix_symlink(struct smbcli_tree
*tree
, const char *fname_src
,
86 const char *fname_dst
)
88 return smbcli_link_internal(tree
, fname_src
, fname_dst
, False
);
91 /****************************************************************************
92 Hard a file (UNIX extensions).
93 ****************************************************************************/
94 NTSTATUS
smbcli_unix_hardlink(struct smbcli_tree
*tree
, const char *fname_src
,
95 const char *fname_dst
)
97 return smbcli_link_internal(tree
, fname_src
, fname_dst
, True
);
101 /****************************************************************************
102 Chmod or chown a file internal (UNIX extensions).
103 ****************************************************************************/
104 static NTSTATUS
smbcli_unix_chmod_chown_internal(struct smbcli_tree
*tree
,
106 uint32_t mode
, uint32_t uid
,
109 union smb_setfileinfo parms
;
112 parms
.generic
.level
= SMB_SFILEINFO_UNIX_BASIC
;
113 parms
.unix_basic
.in
.file
.path
= fname
;
114 parms
.unix_basic
.in
.uid
= uid
;
115 parms
.unix_basic
.in
.gid
= gid
;
116 parms
.unix_basic
.in
.mode
= mode
;
118 status
= smb_raw_setpathinfo(tree
, &parms
);
123 /****************************************************************************
124 chmod a file (UNIX extensions).
125 ****************************************************************************/
127 NTSTATUS
smbcli_unix_chmod(struct smbcli_tree
*tree
, const char *fname
, mode_t mode
)
129 return smbcli_unix_chmod_chown_internal(tree
, fname
,
130 unix_perms_to_wire(mode
),
135 /****************************************************************************
136 chown a file (UNIX extensions).
137 ****************************************************************************/
138 NTSTATUS
smbcli_unix_chown(struct smbcli_tree
*tree
, const char *fname
, uid_t uid
,
141 return smbcli_unix_chmod_chown_internal(tree
, fname
, SMB_MODE_NO_CHANGE
,
142 (uint32_t)uid
, (uint32_t)gid
);
146 /****************************************************************************
148 ****************************************************************************/
149 NTSTATUS
smbcli_rename(struct smbcli_tree
*tree
, const char *fname_src
,
150 const char *fname_dst
)
152 union smb_rename parms
;
154 parms
.generic
.level
= RAW_RENAME_RENAME
;
155 parms
.rename
.in
.attrib
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
156 parms
.rename
.in
.pattern1
= fname_src
;
157 parms
.rename
.in
.pattern2
= fname_dst
;
159 return smb_raw_rename(tree
, &parms
);
163 /****************************************************************************
165 ****************************************************************************/
166 NTSTATUS
smbcli_unlink(struct smbcli_tree
*tree
, const char *fname
)
168 union smb_unlink parms
;
170 parms
.unlink
.in
.pattern
= fname
;
171 if (strchr(fname
, '*')) {
172 parms
.unlink
.in
.attrib
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
174 parms
.unlink
.in
.attrib
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
177 return smb_raw_unlink(tree
, &parms
);
180 /****************************************************************************
182 ****************************************************************************/
183 NTSTATUS
smbcli_mkdir(struct smbcli_tree
*tree
, const char *dname
)
185 union smb_mkdir parms
;
187 parms
.mkdir
.level
= RAW_MKDIR_MKDIR
;
188 parms
.mkdir
.in
.path
= dname
;
190 return smb_raw_mkdir(tree
, &parms
);
194 /****************************************************************************
196 ****************************************************************************/
197 NTSTATUS
smbcli_rmdir(struct smbcli_tree
*tree
, const char *dname
)
199 struct smb_rmdir parms
;
201 parms
.in
.path
= dname
;
203 return smb_raw_rmdir(tree
, &parms
);
207 /****************************************************************************
208 Set or clear the delete on close flag.
209 ****************************************************************************/
210 NTSTATUS
smbcli_nt_delete_on_close(struct smbcli_tree
*tree
, int fnum
, BOOL flag
)
212 union smb_setfileinfo parms
;
215 parms
.disposition_info
.level
= RAW_SFILEINFO_DISPOSITION_INFO
;
216 parms
.disposition_info
.in
.file
.fnum
= fnum
;
217 parms
.disposition_info
.in
.delete_on_close
= flag
;
219 status
= smb_raw_setfileinfo(tree
, &parms
);
225 /****************************************************************************
226 Create/open a file - exposing the full horror of the NT API :-).
227 Used in CIFS-on-CIFS NTVFS.
228 ****************************************************************************/
229 int smbcli_nt_create_full(struct smbcli_tree
*tree
, const char *fname
,
230 uint32_t CreatFlags
, uint32_t DesiredAccess
,
231 uint32_t FileAttributes
, uint32_t ShareAccess
,
232 uint32_t CreateDisposition
, uint32_t CreateOptions
,
233 uint8_t SecurityFlags
)
235 union smb_open open_parms
;
239 mem_ctx
= talloc_init("raw_open");
240 if (!mem_ctx
) return -1;
242 open_parms
.ntcreatex
.level
= RAW_OPEN_NTCREATEX
;
243 open_parms
.ntcreatex
.in
.flags
= CreatFlags
;
244 open_parms
.ntcreatex
.in
.root_fid
= 0;
245 open_parms
.ntcreatex
.in
.access_mask
= DesiredAccess
;
246 open_parms
.ntcreatex
.in
.file_attr
= FileAttributes
;
247 open_parms
.ntcreatex
.in
.alloc_size
= 0;
248 open_parms
.ntcreatex
.in
.share_access
= ShareAccess
;
249 open_parms
.ntcreatex
.in
.open_disposition
= CreateDisposition
;
250 open_parms
.ntcreatex
.in
.create_options
= CreateOptions
;
251 open_parms
.ntcreatex
.in
.impersonation
= 0;
252 open_parms
.ntcreatex
.in
.security_flags
= SecurityFlags
;
253 open_parms
.ntcreatex
.in
.fname
= fname
;
255 status
= smb_raw_open(tree
, mem_ctx
, &open_parms
);
256 talloc_free(mem_ctx
);
258 if (NT_STATUS_IS_OK(status
)) {
259 return open_parms
.ntcreatex
.out
.file
.fnum
;
266 /****************************************************************************
267 Open a file (using SMBopenx)
268 WARNING: if you open with O_WRONLY then getattrE won't work!
269 ****************************************************************************/
270 int smbcli_open(struct smbcli_tree
*tree
, const char *fname
, int flags
,
273 union smb_open open_parms
;
279 mem_ctx
= talloc_init("raw_open");
280 if (!mem_ctx
) return -1;
282 if (flags
& O_CREAT
) {
283 openfn
|= OPENX_OPEN_FUNC_CREATE
;
285 if (!(flags
& O_EXCL
)) {
286 if (flags
& O_TRUNC
) {
287 openfn
|= OPENX_OPEN_FUNC_TRUNC
;
289 openfn
|= OPENX_OPEN_FUNC_OPEN
;
293 accessmode
= (share_mode
<<OPENX_MODE_DENY_SHIFT
);
295 if ((flags
& O_ACCMODE
) == O_RDWR
) {
296 accessmode
|= OPENX_MODE_ACCESS_RDWR
;
297 } else if ((flags
& O_ACCMODE
) == O_WRONLY
) {
298 accessmode
|= OPENX_MODE_ACCESS_WRITE
;
302 if ((flags
& O_SYNC
) == O_SYNC
) {
303 accessmode
|= OPENX_MODE_WRITE_THRU
;
307 if (share_mode
== DENY_FCB
) {
308 accessmode
= OPENX_MODE_ACCESS_FCB
| OPENX_MODE_DENY_FCB
;
311 open_parms
.openx
.level
= RAW_OPEN_OPENX
;
312 open_parms
.openx
.in
.flags
= 0;
313 open_parms
.openx
.in
.open_mode
= accessmode
;
314 open_parms
.openx
.in
.search_attrs
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
;
315 open_parms
.openx
.in
.file_attrs
= 0;
316 open_parms
.openx
.in
.write_time
= 0;
317 open_parms
.openx
.in
.open_func
= openfn
;
318 open_parms
.openx
.in
.size
= 0;
319 open_parms
.openx
.in
.timeout
= 0;
320 open_parms
.openx
.in
.fname
= fname
;
322 status
= smb_raw_open(tree
, mem_ctx
, &open_parms
);
323 talloc_free(mem_ctx
);
325 if (NT_STATUS_IS_OK(status
)) {
326 return open_parms
.openx
.out
.file
.fnum
;
333 /****************************************************************************
335 ****************************************************************************/
336 NTSTATUS
smbcli_close(struct smbcli_tree
*tree
, int fnum
)
338 union smb_close close_parms
;
341 close_parms
.close
.level
= RAW_CLOSE_CLOSE
;
342 close_parms
.close
.in
.file
.fnum
= fnum
;
343 close_parms
.close
.in
.write_time
= 0;
344 status
= smb_raw_close(tree
, &close_parms
);
348 /****************************************************************************
349 send a lock with a specified locktype
350 this is used for testing LOCKING_ANDX_CANCEL_LOCK
351 ****************************************************************************/
352 NTSTATUS
smbcli_locktype(struct smbcli_tree
*tree
, int fnum
,
353 uint32_t offset
, uint32_t len
, int timeout
,
356 union smb_lock parms
;
357 struct smb_lock_entry lock
[1];
360 parms
.lockx
.level
= RAW_LOCK_LOCKX
;
361 parms
.lockx
.in
.file
.fnum
= fnum
;
362 parms
.lockx
.in
.mode
= locktype
;
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
;
369 parms
.lockx
.in
.locks
= &lock
[0];
371 status
= smb_raw_lock(tree
, &parms
);
377 /****************************************************************************
379 ****************************************************************************/
380 NTSTATUS
smbcli_lock(struct smbcli_tree
*tree
, int fnum
,
381 uint32_t offset
, uint32_t len
, int timeout
,
382 enum brl_type lock_type
)
384 union smb_lock parms
;
385 struct smb_lock_entry lock
[1];
388 parms
.lockx
.level
= RAW_LOCK_LOCKX
;
389 parms
.lockx
.in
.file
.fnum
= fnum
;
390 parms
.lockx
.in
.mode
= (lock_type
== READ_LOCK
? 1 : 0);
391 parms
.lockx
.in
.timeout
= timeout
;
392 parms
.lockx
.in
.ulock_cnt
= 0;
393 parms
.lockx
.in
.lock_cnt
= 1;
394 lock
[0].pid
= tree
->session
->pid
;
395 lock
[0].offset
= offset
;
397 parms
.lockx
.in
.locks
= &lock
[0];
399 status
= smb_raw_lock(tree
, &parms
);
405 /****************************************************************************
407 ****************************************************************************/
408 NTSTATUS
smbcli_unlock(struct smbcli_tree
*tree
, int fnum
, uint32_t offset
, uint32_t len
)
410 union smb_lock parms
;
411 struct smb_lock_entry lock
[1];
414 parms
.lockx
.level
= RAW_LOCK_LOCKX
;
415 parms
.lockx
.in
.file
.fnum
= fnum
;
416 parms
.lockx
.in
.mode
= 0;
417 parms
.lockx
.in
.timeout
= 0;
418 parms
.lockx
.in
.ulock_cnt
= 1;
419 parms
.lockx
.in
.lock_cnt
= 0;
420 lock
[0].pid
= tree
->session
->pid
;
421 lock
[0].offset
= offset
;
423 parms
.lockx
.in
.locks
= &lock
[0];
425 status
= smb_raw_lock(tree
, &parms
);
430 /****************************************************************************
431 Lock a file with 64 bit offsets.
432 ****************************************************************************/
433 NTSTATUS
smbcli_lock64(struct smbcli_tree
*tree
, int fnum
,
434 off_t offset
, off_t len
, int timeout
,
435 enum brl_type lock_type
)
437 union smb_lock parms
;
439 struct smb_lock_entry lock
[1];
442 if (!(tree
->session
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
443 return smbcli_lock(tree
, fnum
, offset
, len
, timeout
, lock_type
);
446 parms
.lockx
.level
= RAW_LOCK_LOCKX
;
447 parms
.lockx
.in
.file
.fnum
= fnum
;
449 ltype
= (lock_type
== READ_LOCK
? 1 : 0);
450 ltype
|= LOCKING_ANDX_LARGE_FILES
;
451 parms
.lockx
.in
.mode
= ltype
;
452 parms
.lockx
.in
.timeout
= timeout
;
453 parms
.lockx
.in
.ulock_cnt
= 0;
454 parms
.lockx
.in
.lock_cnt
= 1;
455 lock
[0].pid
= tree
->session
->pid
;
456 lock
[0].offset
= offset
;
458 parms
.lockx
.in
.locks
= &lock
[0];
460 status
= smb_raw_lock(tree
, &parms
);
466 /****************************************************************************
467 Unlock a file with 64 bit offsets.
468 ****************************************************************************/
469 NTSTATUS
smbcli_unlock64(struct smbcli_tree
*tree
, int fnum
, off_t offset
,
472 union smb_lock parms
;
473 struct smb_lock_entry lock
[1];
476 if (!(tree
->session
->transport
->negotiate
.capabilities
& CAP_LARGE_FILES
)) {
477 return smbcli_unlock(tree
, fnum
, offset
, len
);
480 parms
.lockx
.level
= RAW_LOCK_LOCKX
;
481 parms
.lockx
.in
.file
.fnum
= fnum
;
482 parms
.lockx
.in
.mode
= LOCKING_ANDX_LARGE_FILES
;
483 parms
.lockx
.in
.timeout
= 0;
484 parms
.lockx
.in
.ulock_cnt
= 1;
485 parms
.lockx
.in
.lock_cnt
= 0;
486 lock
[0].pid
= tree
->session
->pid
;
487 lock
[0].offset
= offset
;
489 parms
.lockx
.in
.locks
= &lock
[0];
491 status
= smb_raw_lock(tree
, &parms
);
497 /****************************************************************************
498 Do a SMBgetattrE call.
499 ****************************************************************************/
500 NTSTATUS
smbcli_getattrE(struct smbcli_tree
*tree
, int fnum
,
501 uint16_t *attr
, size_t *size
,
502 time_t *c_time
, time_t *a_time
, time_t *m_time
)
504 union smb_fileinfo parms
;
507 parms
.getattre
.level
= RAW_FILEINFO_GETATTRE
;
508 parms
.getattre
.in
.file
.fnum
= fnum
;
510 status
= smb_raw_fileinfo(tree
, NULL
, &parms
);
512 if (!NT_STATUS_IS_OK(status
))
516 *size
= parms
.getattre
.out
.size
;
520 *attr
= parms
.getattre
.out
.attrib
;
524 *c_time
= parms
.getattre
.out
.create_time
;
528 *a_time
= parms
.getattre
.out
.access_time
;
532 *m_time
= parms
.getattre
.out
.write_time
;
538 /****************************************************************************
540 ****************************************************************************/
541 NTSTATUS
smbcli_getatr(struct smbcli_tree
*tree
, const char *fname
,
542 uint16_t *attr
, size_t *size
, time_t *t
)
544 union smb_fileinfo parms
;
547 parms
.getattr
.level
= RAW_FILEINFO_GETATTR
;
548 parms
.getattr
.in
.file
.path
= fname
;
550 status
= smb_raw_pathinfo(tree
, NULL
, &parms
);
552 if (!NT_STATUS_IS_OK(status
)) {
557 *size
= parms
.getattr
.out
.size
;
561 *t
= parms
.getattr
.out
.write_time
;
565 *attr
= parms
.getattr
.out
.attrib
;
572 /****************************************************************************
574 ****************************************************************************/
575 NTSTATUS
smbcli_setatr(struct smbcli_tree
*tree
, const char *fname
, uint16_t mode
,
578 union smb_setfileinfo parms
;
580 parms
.setattr
.level
= RAW_SFILEINFO_SETATTR
;
581 parms
.setattr
.in
.file
.path
= fname
;
582 parms
.setattr
.in
.attrib
= mode
;
583 parms
.setattr
.in
.write_time
= t
;
585 return smb_raw_setpathinfo(tree
, &parms
);
588 /****************************************************************************
589 Do a setfileinfo basic_info call.
590 ****************************************************************************/
591 NTSTATUS
smbcli_fsetatr(struct smbcli_tree
*tree
, int fnum
, uint16_t mode
,
592 NTTIME create_time
, NTTIME access_time
,
593 NTTIME write_time
, NTTIME change_time
)
595 union smb_setfileinfo parms
;
597 parms
.basic_info
.level
= RAW_SFILEINFO_BASIC_INFO
;
598 parms
.basic_info
.in
.file
.fnum
= fnum
;
599 parms
.basic_info
.in
.attrib
= mode
;
600 parms
.basic_info
.in
.create_time
= create_time
;
601 parms
.basic_info
.in
.access_time
= access_time
;
602 parms
.basic_info
.in
.write_time
= write_time
;
603 parms
.basic_info
.in
.change_time
= change_time
;
605 return smb_raw_setfileinfo(tree
, &parms
);
609 /****************************************************************************
610 truncate a file to a given size
611 ****************************************************************************/
612 NTSTATUS
smbcli_ftruncate(struct smbcli_tree
*tree
, int fnum
, uint64_t size
)
614 union smb_setfileinfo parms
;
616 parms
.end_of_file_info
.level
= RAW_SFILEINFO_END_OF_FILE_INFO
;
617 parms
.end_of_file_info
.in
.file
.fnum
= fnum
;
618 parms
.end_of_file_info
.in
.size
= size
;
620 return smb_raw_setfileinfo(tree
, &parms
);
624 /****************************************************************************
625 Check for existence of a dir.
626 ****************************************************************************/
627 NTSTATUS
smbcli_chkpath(struct smbcli_tree
*tree
, const char *path
)
629 union smb_chkpath parms
;
633 path2
= strdup(path
);
634 trim_string(path2
,NULL
,"\\");
637 path2
= strdup("\\");
640 parms
.chkpath
.in
.path
= path2
;
642 status
= smb_raw_chkpath(tree
, &parms
);
650 /****************************************************************************
652 ****************************************************************************/
653 NTSTATUS
smbcli_dskattr(struct smbcli_tree
*tree
, int *bsize
, int *total
, int *avail
)
655 union smb_fsinfo fsinfo_parms
;
659 mem_ctx
= talloc_init("smbcli_dskattr");
661 fsinfo_parms
.dskattr
.level
= RAW_QFS_DSKATTR
;
662 status
= smb_raw_fsinfo(tree
, mem_ctx
, &fsinfo_parms
);
663 if (NT_STATUS_IS_OK(status
)) {
664 *bsize
= fsinfo_parms
.dskattr
.out
.block_size
;
665 *total
= fsinfo_parms
.dskattr
.out
.units_total
;
666 *avail
= fsinfo_parms
.dskattr
.out
.units_free
;
669 talloc_free(mem_ctx
);
675 /****************************************************************************
676 Create and open a temporary file.
677 ****************************************************************************/
678 int smbcli_ctemp(struct smbcli_tree
*tree
, const char *path
, char **tmp_path
)
680 union smb_open open_parms
;
684 mem_ctx
= talloc_init("raw_open");
685 if (!mem_ctx
) return -1;
687 open_parms
.openx
.level
= RAW_OPEN_CTEMP
;
688 open_parms
.ctemp
.in
.attrib
= 0;
689 open_parms
.ctemp
.in
.directory
= path
;
690 open_parms
.ctemp
.in
.write_time
= 0;
692 status
= smb_raw_open(tree
, mem_ctx
, &open_parms
);
694 *tmp_path
= strdup(open_parms
.ctemp
.out
.name
);
696 talloc_free(mem_ctx
);
697 if (NT_STATUS_IS_OK(status
)) {
698 return open_parms
.ctemp
.out
.file
.fnum
;