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 "libcli/raw/libcliraw.h"
26 /****************************************************************************
27 Hard/Symlink a file (UNIX extensions).
28 ****************************************************************************/
30 static NTSTATUS smbcli_link_internal(struct smbcli_tree *tree,
31 const char *fname_src,
32 const char *fname_dst, BOOL hard_link)
34 union smb_setfileinfo parms;
38 parms.generic.level = RAW_SFILEINFO_UNIX_HLINK;
39 parms.unix_hlink.file.fname = fname_src;
40 parms.unix_hlink.in.link_dest = fname_dst;
42 parms.generic.level = RAW_SFILEINFO_UNIX_LINK;
43 parms.unix_link.file.fname = fname_src;
44 parms.unix_link.in.link_dest = fname_dst;
47 status = smb_raw_setpathinfo(tree, &parms);
52 /****************************************************************************
53 Map standard UNIX permissions onto wire representations.
54 ****************************************************************************/
55 uint32_t unix_perms_to_wire(mode_t perms)
59 ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0);
60 ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0);
61 ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0);
62 ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0);
63 ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0);
64 ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0);
65 ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0);
66 ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0);
67 ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0);
69 ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0);
72 ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0);
75 ret |= ((perms & S_ISUID) ? UNIX_SET_UID : 0);
80 /****************************************************************************
81 Symlink a file (UNIX extensions).
82 ****************************************************************************/
83 NTSTATUS smbcli_unix_symlink(struct smbcli_tree *tree, const char *fname_src,
84 const char *fname_dst)
86 return smbcli_link_internal(tree, fname_src, fname_dst, False);
89 /****************************************************************************
90 Hard a file (UNIX extensions).
91 ****************************************************************************/
92 NTSTATUS smbcli_unix_hardlink(struct smbcli_tree *tree, const char *fname_src,
93 const char *fname_dst)
95 return smbcli_link_internal(tree, fname_src, fname_dst, True);
99 /****************************************************************************
100 Chmod or chown a file internal (UNIX extensions).
101 ****************************************************************************/
102 static NTSTATUS smbcli_unix_chmod_chown_internal(struct smbcli_tree *tree,
104 uint32_t mode, uint32_t uid,
107 union smb_setfileinfo parms;
110 parms.generic.level = SMB_SFILEINFO_UNIX_BASIC;
111 parms.unix_basic.file.fname = fname;
112 parms.unix_basic.in.uid = uid;
113 parms.unix_basic.in.gid = gid;
114 parms.unix_basic.in.mode = mode;
116 status = smb_raw_setpathinfo(tree, &parms);
121 /****************************************************************************
122 chmod a file (UNIX extensions).
123 ****************************************************************************/
125 NTSTATUS smbcli_unix_chmod(struct smbcli_tree *tree, const char *fname, mode_t mode)
127 return smbcli_unix_chmod_chown_internal(tree, fname,
128 unix_perms_to_wire(mode),
133 /****************************************************************************
134 chown a file (UNIX extensions).
135 ****************************************************************************/
136 NTSTATUS smbcli_unix_chown(struct smbcli_tree *tree, const char *fname, uid_t uid,
139 return smbcli_unix_chmod_chown_internal(tree, fname, SMB_MODE_NO_CHANGE,
140 (uint32_t)uid, (uint32_t)gid);
144 /****************************************************************************
146 ****************************************************************************/
147 NTSTATUS smbcli_rename(struct smbcli_tree *tree, const char *fname_src,
148 const char *fname_dst)
150 union smb_rename parms;
152 parms.generic.level = RAW_RENAME_RENAME;
153 parms.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
154 parms.rename.in.pattern1 = fname_src;
155 parms.rename.in.pattern2 = fname_dst;
157 return smb_raw_rename(tree, &parms);
161 /****************************************************************************
163 ****************************************************************************/
164 NTSTATUS smbcli_unlink(struct smbcli_tree *tree, const char *fname)
166 struct smb_unlink parms;
168 parms.in.pattern = fname;
169 if (strchr(fname, '*')) {
170 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
172 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
175 return smb_raw_unlink(tree, &parms);
178 /****************************************************************************
180 ****************************************************************************/
181 NTSTATUS smbcli_mkdir(struct smbcli_tree *tree, const char *dname)
183 union smb_mkdir parms;
185 parms.mkdir.level = RAW_MKDIR_MKDIR;
186 parms.mkdir.in.path = dname;
188 return smb_raw_mkdir(tree, &parms);
192 /****************************************************************************
194 ****************************************************************************/
195 NTSTATUS smbcli_rmdir(struct smbcli_tree *tree, const char *dname)
197 struct smb_rmdir parms;
199 parms.in.path = dname;
201 return smb_raw_rmdir(tree, &parms);
205 /****************************************************************************
206 Set or clear the delete on close flag.
207 ****************************************************************************/
208 NTSTATUS smbcli_nt_delete_on_close(struct smbcli_tree *tree, int fnum, BOOL flag)
210 union smb_setfileinfo parms;
213 parms.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
214 parms.disposition_info.file.fnum = fnum;
215 parms.disposition_info.in.delete_on_close = flag;
217 status = smb_raw_setfileinfo(tree, &parms);
223 /****************************************************************************
224 Create/open a file - exposing the full horror of the NT API :-).
225 Used in CIFS-on-CIFS NTVFS.
226 ****************************************************************************/
227 int smbcli_nt_create_full(struct smbcli_tree *tree, const char *fname,
228 uint32_t CreatFlags, uint32_t DesiredAccess,
229 uint32_t FileAttributes, uint32_t ShareAccess,
230 uint32_t CreateDisposition, uint32_t CreateOptions,
231 uint8_t SecurityFlags)
233 union smb_open open_parms;
237 mem_ctx = talloc_init("raw_open");
238 if (!mem_ctx) return -1;
240 open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
241 open_parms.ntcreatex.in.flags = CreatFlags;
242 open_parms.ntcreatex.in.root_fid = 0;
243 open_parms.ntcreatex.in.access_mask = DesiredAccess;
244 open_parms.ntcreatex.in.file_attr = FileAttributes;
245 open_parms.ntcreatex.in.alloc_size = 0;
246 open_parms.ntcreatex.in.share_access = ShareAccess;
247 open_parms.ntcreatex.in.open_disposition = CreateDisposition;
248 open_parms.ntcreatex.in.create_options = CreateOptions;
249 open_parms.ntcreatex.in.impersonation = 0;
250 open_parms.ntcreatex.in.security_flags = SecurityFlags;
251 open_parms.ntcreatex.in.fname = fname;
253 status = smb_raw_open(tree, mem_ctx, &open_parms);
254 talloc_destroy(mem_ctx);
256 if (NT_STATUS_IS_OK(status)) {
257 return open_parms.ntcreatex.out.fnum;
264 /****************************************************************************
265 Open a file (using SMBopenx)
266 WARNING: if you open with O_WRONLY then getattrE won't work!
267 ****************************************************************************/
268 int smbcli_open(struct smbcli_tree *tree, const char *fname, int flags,
271 union smb_open open_parms;
277 mem_ctx = talloc_init("raw_open");
278 if (!mem_ctx) return -1;
280 if (flags & O_CREAT) {
281 openfn |= OPENX_OPEN_FUNC_CREATE;
283 if (!(flags & O_EXCL)) {
284 if (flags & O_TRUNC) {
285 openfn |= OPENX_OPEN_FUNC_TRUNC;
287 openfn |= OPENX_OPEN_FUNC_OPEN;
291 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
293 if ((flags & O_ACCMODE) == O_RDWR) {
294 accessmode |= OPENX_MODE_ACCESS_RDWR;
295 } else if ((flags & O_ACCMODE) == O_WRONLY) {
296 accessmode |= OPENX_MODE_ACCESS_WRITE;
300 if ((flags & O_SYNC) == O_SYNC) {
301 accessmode |= OPENX_MODE_WRITE_THRU;
305 if (share_mode == DENY_FCB) {
306 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
309 open_parms.openx.level = RAW_OPEN_OPENX;
310 open_parms.openx.in.flags = 0;
311 open_parms.openx.in.open_mode = accessmode;
312 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
313 open_parms.openx.in.file_attrs = 0;
314 open_parms.openx.in.write_time = 0;
315 open_parms.openx.in.open_func = openfn;
316 open_parms.openx.in.size = 0;
317 open_parms.openx.in.timeout = 0;
318 open_parms.openx.in.fname = fname;
320 status = smb_raw_open(tree, mem_ctx, &open_parms);
321 talloc_destroy(mem_ctx);
323 if (NT_STATUS_IS_OK(status)) {
324 return open_parms.openx.out.fnum;
331 /****************************************************************************
333 ****************************************************************************/
334 NTSTATUS smbcli_close(struct smbcli_tree *tree, int fnum)
336 union smb_close close_parms;
339 close_parms.close.level = RAW_CLOSE_CLOSE;
340 close_parms.close.in.fnum = fnum;
341 close_parms.close.in.write_time = 0;
342 status = smb_raw_close(tree, &close_parms);
346 /****************************************************************************
347 send a lock with a specified locktype
348 this is used for testing LOCKING_ANDX_CANCEL_LOCK
349 ****************************************************************************/
350 NTSTATUS smbcli_locktype(struct smbcli_tree *tree, int fnum,
351 uint32_t offset, uint32_t len, int timeout,
354 union smb_lock parms;
355 struct smb_lock_entry lock[1];
358 parms.lockx.level = RAW_LOCK_LOCKX;
359 parms.lockx.in.fnum = fnum;
360 parms.lockx.in.mode = locktype;
361 parms.lockx.in.timeout = timeout;
362 parms.lockx.in.ulock_cnt = 0;
363 parms.lockx.in.lock_cnt = 1;
364 lock[0].pid = tree->session->pid;
365 lock[0].offset = offset;
367 parms.lockx.in.locks = &lock[0];
369 status = smb_raw_lock(tree, &parms);
375 /****************************************************************************
377 ****************************************************************************/
378 NTSTATUS smbcli_lock(struct smbcli_tree *tree, int fnum,
379 uint32_t offset, uint32_t len, int timeout,
380 enum brl_type lock_type)
382 union smb_lock parms;
383 struct smb_lock_entry lock[1];
386 parms.lockx.level = RAW_LOCK_LOCKX;
387 parms.lockx.in.fnum = fnum;
388 parms.lockx.in.mode = (lock_type == READ_LOCK? 1 : 0);
389 parms.lockx.in.timeout = timeout;
390 parms.lockx.in.ulock_cnt = 0;
391 parms.lockx.in.lock_cnt = 1;
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);
403 /****************************************************************************
405 ****************************************************************************/
406 NTSTATUS smbcli_unlock(struct smbcli_tree *tree, int fnum, uint32_t offset, uint32_t len)
408 union smb_lock parms;
409 struct smb_lock_entry lock[1];
412 parms.lockx.level = RAW_LOCK_LOCKX;
413 parms.lockx.in.fnum = fnum;
414 parms.lockx.in.mode = 0;
415 parms.lockx.in.timeout = 0;
416 parms.lockx.in.ulock_cnt = 1;
417 parms.lockx.in.lock_cnt = 0;
418 lock[0].pid = tree->session->pid;
419 lock[0].offset = offset;
421 parms.lockx.in.locks = &lock[0];
423 status = smb_raw_lock(tree, &parms);
428 /****************************************************************************
429 Lock a file with 64 bit offsets.
430 ****************************************************************************/
431 NTSTATUS smbcli_lock64(struct smbcli_tree *tree, int fnum,
432 off_t offset, off_t len, int timeout,
433 enum brl_type lock_type)
435 union smb_lock parms;
437 struct smb_lock_entry lock[1];
440 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
441 return smbcli_lock(tree, fnum, offset, len, timeout, lock_type);
444 parms.lockx.level = RAW_LOCK_LOCKX;
445 parms.lockx.in.fnum = fnum;
447 ltype = (lock_type == READ_LOCK? 1 : 0);
448 ltype |= LOCKING_ANDX_LARGE_FILES;
449 parms.lockx.in.mode = ltype;
450 parms.lockx.in.timeout = timeout;
451 parms.lockx.in.ulock_cnt = 0;
452 parms.lockx.in.lock_cnt = 1;
453 lock[0].pid = tree->session->pid;
454 lock[0].offset = offset;
456 parms.lockx.in.locks = &lock[0];
458 status = smb_raw_lock(tree, &parms);
464 /****************************************************************************
465 Unlock a file with 64 bit offsets.
466 ****************************************************************************/
467 NTSTATUS smbcli_unlock64(struct smbcli_tree *tree, int fnum, off_t offset,
470 union smb_lock parms;
471 struct smb_lock_entry lock[1];
474 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
475 return smbcli_unlock(tree, fnum, offset, len);
478 parms.lockx.level = RAW_LOCK_LOCKX;
479 parms.lockx.in.fnum = fnum;
480 parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
481 parms.lockx.in.timeout = 0;
482 parms.lockx.in.ulock_cnt = 1;
483 parms.lockx.in.lock_cnt = 0;
484 lock[0].pid = tree->session->pid;
485 lock[0].offset = offset;
487 parms.lockx.in.locks = &lock[0];
489 status = smb_raw_lock(tree, &parms);
495 /****************************************************************************
496 Do a SMBgetattrE call.
497 ****************************************************************************/
498 NTSTATUS smbcli_getattrE(struct smbcli_tree *tree, int fnum,
499 uint16_t *attr, size_t *size,
500 time_t *c_time, time_t *a_time, time_t *m_time)
502 union smb_fileinfo parms;
505 parms.getattre.level = RAW_FILEINFO_GETATTRE;
506 parms.getattre.in.fnum = fnum;
508 status = smb_raw_fileinfo(tree, NULL, &parms);
510 if (!NT_STATUS_IS_OK(status))
514 *size = parms.getattre.out.size;
518 *attr = parms.getattre.out.attrib;
522 *c_time = parms.getattre.out.create_time;
526 *a_time = parms.getattre.out.access_time;
530 *m_time = parms.getattre.out.write_time;
536 /****************************************************************************
538 ****************************************************************************/
539 NTSTATUS smbcli_getatr(struct smbcli_tree *tree, const char *fname,
540 uint16_t *attr, size_t *size, time_t *t)
542 union smb_fileinfo parms;
545 parms.getattr.level = RAW_FILEINFO_GETATTR;
546 parms.getattr.in.fname = fname;
548 status = smb_raw_pathinfo(tree, NULL, &parms);
550 if (!NT_STATUS_IS_OK(status)) {
555 *size = parms.getattr.out.size;
559 *t = parms.getattr.out.write_time;
563 *attr = parms.getattr.out.attrib;
570 /****************************************************************************
572 ****************************************************************************/
573 NTSTATUS smbcli_setatr(struct smbcli_tree *tree, const char *fname, uint16_t mode,
576 union smb_setfileinfo parms;
579 parms.setattr.level = RAW_SFILEINFO_SETATTR;
580 parms.setattr.in.attrib = mode;
581 parms.setattr.in.write_time = t;
582 parms.setattr.file.fname = fname;
584 status = smb_raw_setpathinfo(tree, &parms);
590 /****************************************************************************
591 Check for existence of a dir.
592 ****************************************************************************/
593 NTSTATUS smbcli_chkpath(struct smbcli_tree *tree, const char *path)
595 struct smb_chkpath parms;
599 path2 = strdup(path);
600 trim_string(path2,NULL,"\\");
603 path2 = strdup("\\");
606 parms.in.path = path2;
608 status = smb_raw_chkpath(tree, &parms);
616 /****************************************************************************
618 ****************************************************************************/
619 NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, int *bsize, int *total, int *avail)
621 union smb_fsinfo fsinfo_parms;
625 mem_ctx = talloc_init("smbcli_dskattr");
627 fsinfo_parms.dskattr.level = RAW_QFS_DSKATTR;
628 status = smb_raw_fsinfo(tree, mem_ctx, &fsinfo_parms);
629 if (NT_STATUS_IS_OK(status)) {
630 *bsize = fsinfo_parms.dskattr.out.block_size;
631 *total = fsinfo_parms.dskattr.out.units_total;
632 *avail = fsinfo_parms.dskattr.out.units_free;
635 talloc_destroy(mem_ctx);
641 /****************************************************************************
642 Create and open a temporary file.
643 ****************************************************************************/
644 int smbcli_ctemp(struct smbcli_tree *tree, const char *path, char **tmp_path)
646 union smb_open open_parms;
650 mem_ctx = talloc_init("raw_open");
651 if (!mem_ctx) return -1;
653 open_parms.openx.level = RAW_OPEN_CTEMP;
654 open_parms.ctemp.in.attrib = 0;
655 open_parms.ctemp.in.directory = path;
656 open_parms.ctemp.in.write_time = 0;
658 status = smb_raw_open(tree, mem_ctx, &open_parms);
660 *tmp_path = strdup(open_parms.ctemp.out.name);
662 talloc_destroy(mem_ctx);
663 if (NT_STATUS_IS_OK(status)) {
664 return open_parms.ctemp.out.fnum;