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 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/>.
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
;
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
;
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
);
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
,
77 uint32_t mode
, uint32_t uid
,
80 union smb_setfileinfo parms
;
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
);
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
),
106 /****************************************************************************
107 chown a file (UNIX extensions).
108 ****************************************************************************/
109 NTSTATUS
smbcli_unix_chown(struct smbcli_tree
*tree
, const char *fname
, uid_t uid
,
112 return smbcli_unix_chmod_chown_internal(tree
, fname
, SMB_MODE_NO_CHANGE
,
113 (uint32_t)uid
, (uint32_t)gid
);
117 /****************************************************************************
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 /****************************************************************************
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
;
145 parms
.unlink
.in
.attrib
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
148 return smb_raw_unlink(tree
, &parms
);
151 /****************************************************************************
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 /****************************************************************************
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
,
184 union smb_setfileinfo parms
;
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
);
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
;
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
;
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
,
245 union smb_open open_parms
;
246 unsigned int openfn
=0;
247 unsigned int accessmode
=0;
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
;
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
;
274 if ((flags
& O_SYNC
) == O_SYNC
) {
275 accessmode
|= OPENX_MODE_WRITE_THRU
;
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
;
305 /****************************************************************************
307 ****************************************************************************/
308 NTSTATUS
smbcli_close(struct smbcli_tree
*tree
, int fnum
)
310 union smb_close close_parms
;
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
);
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
,
328 union smb_lock parms
;
329 struct smb_lock_entry lock
[1];
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
;
341 parms
.lockx
.in
.locks
= &lock
[0];
343 status
= smb_raw_lock(tree
, &parms
);
349 /****************************************************************************
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];
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
;
369 parms
.lockx
.in
.locks
= &lock
[0];
371 status
= smb_raw_lock(tree
, &parms
);
377 /****************************************************************************
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];
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
;
395 parms
.lockx
.in
.locks
= &lock
[0];
397 status
= smb_raw_lock(tree
, &parms
);
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
;
411 struct smb_lock_entry lock
[1];
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
;
430 parms
.lockx
.in
.locks
= &lock
[0];
432 status
= smb_raw_lock(tree
, &parms
);
438 /****************************************************************************
439 Unlock a file with 64 bit offsets.
440 ****************************************************************************/
441 NTSTATUS
smbcli_unlock64(struct smbcli_tree
*tree
, int fnum
, off_t offset
,
444 union smb_lock parms
;
445 struct smb_lock_entry lock
[1];
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
;
461 parms
.lockx
.in
.locks
= &lock
[0];
463 status
= smb_raw_lock(tree
, &parms
);
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
;
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
))
488 *size
= parms
.getattre
.out
.size
;
492 *attr
= parms
.getattre
.out
.attrib
;
496 *c_time
= parms
.getattre
.out
.create_time
;
500 *a_time
= parms
.getattre
.out
.access_time
;
504 *m_time
= parms
.getattre
.out
.write_time
;
510 /****************************************************************************
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
;
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
)) {
529 *size
= parms
.getattr
.out
.size
;
533 *t
= parms
.getattr
.out
.write_time
;
537 *attr
= parms
.getattr
.out
.attrib
;
544 /****************************************************************************
546 ****************************************************************************/
547 NTSTATUS
smbcli_setatr(struct smbcli_tree
*tree
, const char *fname
, uint16_t mode
,
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
;
605 path2
= strdup(path
);
606 trim_string(path2
,NULL
,"\\");
609 path2
= strdup("\\");
612 parms
.chkpath
.in
.path
= path2
;
614 status
= smb_raw_chkpath(tree
, &parms
);
622 /****************************************************************************
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
;
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
);
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
;
657 mem_ctx
= talloc_init("raw_open");
658 if (!mem_ctx
) return -1;
660 open_parms
.openx
.level
= RAW_OPEN_CTEMP
;
661 open_parms
.ctemp
.in
.attrib
= 0;
662 open_parms
.ctemp
.in
.directory
= path
;
663 open_parms
.ctemp
.in
.write_time
= 0;
665 status
= smb_raw_open(tree
, mem_ctx
, &open_parms
);
667 *tmp_path
= strdup(open_parms
.ctemp
.out
.name
);
669 talloc_free(mem_ctx
);
670 if (NT_STATUS_IS_OK(status
)) {
671 return open_parms
.ctemp
.out
.file
.fnum
;