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"
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
.file
.fname
= fname_src
;
41 parms
.unix_hlink
.in
.link_dest
= fname_dst
;
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
);
53 /****************************************************************************
54 Map standard UNIX permissions onto wire representations.
55 ****************************************************************************/
56 uint32_t unix_perms_to_wire(mode_t perms
)
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);
70 ret
|= ((perms
& S_ISVTX
) ? UNIX_STICKY
: 0);
73 ret
|= ((perms
& S_ISGID
) ? UNIX_SET_GID
: 0);
76 ret
|= ((perms
& S_ISUID
) ? UNIX_SET_UID
: 0);
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
,
105 uint32_t mode
, uint32_t uid
,
108 union smb_setfileinfo parms
;
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
);
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
),
134 /****************************************************************************
135 chown a file (UNIX extensions).
136 ****************************************************************************/
137 NTSTATUS
smbcli_unix_chown(struct smbcli_tree
*tree
, const char *fname
, uid_t uid
,
140 return smbcli_unix_chmod_chown_internal(tree
, fname
, SMB_MODE_NO_CHANGE
,
141 (uint32_t)uid
, (uint32_t)gid
);
145 /****************************************************************************
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 /****************************************************************************
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
;
173 parms
.in
.attrib
= FILE_ATTRIBUTE_SYSTEM
| FILE_ATTRIBUTE_HIDDEN
| FILE_ATTRIBUTE_DIRECTORY
;
176 return smb_raw_unlink(tree
, &parms
);
179 /****************************************************************************
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 /****************************************************************************
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
;
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
);
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
;
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
;
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
,
272 union smb_open open_parms
;
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
;
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
;
301 if ((flags
& O_SYNC
) == O_SYNC
) {
302 accessmode
|= OPENX_MODE_WRITE_THRU
;
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
;
332 /****************************************************************************
334 ****************************************************************************/
335 NTSTATUS
smbcli_close(struct smbcli_tree
*tree
, int fnum
)
337 union smb_close close_parms
;
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
);
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
,
355 union smb_lock parms
;
356 struct smb_lock_entry lock
[1];
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
;
368 parms
.lockx
.in
.locks
= &lock
[0];
370 status
= smb_raw_lock(tree
, &parms
);
376 /****************************************************************************
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];
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
;
396 parms
.lockx
.in
.locks
= &lock
[0];
398 status
= smb_raw_lock(tree
, &parms
);
404 /****************************************************************************
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];
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
;
422 parms
.lockx
.in
.locks
= &lock
[0];
424 status
= smb_raw_lock(tree
, &parms
);
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
;
438 struct smb_lock_entry lock
[1];
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
;
457 parms
.lockx
.in
.locks
= &lock
[0];
459 status
= smb_raw_lock(tree
, &parms
);
465 /****************************************************************************
466 Unlock a file with 64 bit offsets.
467 ****************************************************************************/
468 NTSTATUS
smbcli_unlock64(struct smbcli_tree
*tree
, int fnum
, off_t offset
,
471 union smb_lock parms
;
472 struct smb_lock_entry lock
[1];
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
;
488 parms
.lockx
.in
.locks
= &lock
[0];
490 status
= smb_raw_lock(tree
, &parms
);
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
;
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
))
515 *size
= parms
.getattre
.out
.size
;
519 *attr
= parms
.getattre
.out
.attrib
;
523 *c_time
= parms
.getattre
.out
.create_time
;
527 *a_time
= parms
.getattre
.out
.access_time
;
531 *m_time
= parms
.getattre
.out
.write_time
;
537 /****************************************************************************
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
;
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
)) {
556 *size
= parms
.getattr
.out
.size
;
560 *t
= parms
.getattr
.out
.write_time
;
564 *attr
= parms
.getattr
.out
.attrib
;
571 /****************************************************************************
573 ****************************************************************************/
574 NTSTATUS
smbcli_setatr(struct smbcli_tree
*tree
, const char *fname
, uint16_t mode
,
577 union smb_setfileinfo parms
;
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
);
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
;
600 path2
= strdup(path
);
601 trim_string(path2
,NULL
,"\\");
604 path2
= strdup("\\");
607 parms
.in
.path
= path2
;
609 status
= smb_raw_chkpath(tree
, &parms
);
617 /****************************************************************************
619 ****************************************************************************/
620 NTSTATUS
smbcli_dskattr(struct smbcli_tree
*tree
, int *bsize
, int *total
, int *avail
)
622 union smb_fsinfo fsinfo_parms
;
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
);
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
;
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
);
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
;