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.
25 /****************************************************************************
26 Hard/Symlink a file (UNIX extensions).
27 ****************************************************************************/
29 static NTSTATUS cli_link_internal(struct cli_tree *tree,
30 const char *fname_src,
31 const char *fname_dst, BOOL hard_link)
33 union smb_setfileinfo parms;
37 parms.generic.level = RAW_SFILEINFO_UNIX_HLINK;
38 parms.unix_hlink.file.fname = fname_src;
39 parms.unix_hlink.in.link_dest = fname_dst;
41 parms.generic.level = RAW_SFILEINFO_UNIX_LINK;
42 parms.unix_link.file.fname = fname_src;
43 parms.unix_link.in.link_dest = fname_dst;
46 status = smb_raw_setpathinfo(tree, &parms);
51 /****************************************************************************
52 Map standard UNIX permissions onto wire representations.
53 ****************************************************************************/
54 static uint32_t unix_perms_to_wire(mode_t perms)
58 ret |= ((perms & S_IXOTH) ? UNIX_X_OTH : 0);
59 ret |= ((perms & S_IWOTH) ? UNIX_W_OTH : 0);
60 ret |= ((perms & S_IROTH) ? UNIX_R_OTH : 0);
61 ret |= ((perms & S_IXGRP) ? UNIX_X_GRP : 0);
62 ret |= ((perms & S_IWGRP) ? UNIX_W_GRP : 0);
63 ret |= ((perms & S_IRGRP) ? UNIX_R_GRP : 0);
64 ret |= ((perms & S_IXUSR) ? UNIX_X_USR : 0);
65 ret |= ((perms & S_IWUSR) ? UNIX_W_USR : 0);
66 ret |= ((perms & S_IRUSR) ? UNIX_R_USR : 0);
68 ret |= ((perms & S_ISVTX) ? UNIX_STICKY : 0);
71 ret |= ((perms & S_ISGID) ? UNIX_SET_GID : 0);
74 ret |= ((perms & S_ISUID) ? UNIX_SET_UID : 0);
79 /****************************************************************************
80 Symlink a file (UNIX extensions).
81 ****************************************************************************/
82 NTSTATUS cli_unix_symlink(struct cli_tree *tree, const char *fname_src,
83 const char *fname_dst)
85 return cli_link_internal(tree, fname_src, fname_dst, False);
88 /****************************************************************************
89 Hard a file (UNIX extensions).
90 ****************************************************************************/
91 NTSTATUS cli_unix_hardlink(struct cli_tree *tree, const char *fname_src,
92 const char *fname_dst)
94 return cli_link_internal(tree, fname_src, fname_dst, True);
98 /****************************************************************************
99 Chmod or chown a file internal (UNIX extensions).
100 ****************************************************************************/
101 static NTSTATUS cli_unix_chmod_chown_internal(struct cli_tree *tree,
103 uint32_t mode, uint32_t uid,
106 union smb_setfileinfo parms;
109 parms.generic.level = SMB_SFILEINFO_UNIX_BASIC;
110 parms.unix_basic.file.fname = fname;
111 parms.unix_basic.in.uid = uid;
112 parms.unix_basic.in.gid = gid;
113 parms.unix_basic.in.mode = mode;
115 status = smb_raw_setpathinfo(tree, &parms);
120 /****************************************************************************
121 chmod a file (UNIX extensions).
122 ****************************************************************************/
124 NTSTATUS cli_unix_chmod(struct cli_tree *tree, const char *fname, mode_t mode)
126 return cli_unix_chmod_chown_internal(tree, fname,
127 unix_perms_to_wire(mode),
132 /****************************************************************************
133 chown a file (UNIX extensions).
134 ****************************************************************************/
135 NTSTATUS cli_unix_chown(struct cli_tree *tree, const char *fname, uid_t uid,
138 return cli_unix_chmod_chown_internal(tree, fname, SMB_MODE_NO_CHANGE,
139 (uint32_t)uid, (uint32_t)gid);
143 /****************************************************************************
145 ****************************************************************************/
146 NTSTATUS cli_rename(struct cli_tree *tree, const char *fname_src,
147 const char *fname_dst)
149 union smb_rename parms;
151 parms.generic.level = RAW_RENAME_RENAME;
152 parms.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
153 parms.rename.in.pattern1 = fname_src;
154 parms.rename.in.pattern2 = fname_dst;
156 return smb_raw_rename(tree, &parms);
160 /****************************************************************************
162 ****************************************************************************/
163 NTSTATUS cli_unlink(struct cli_tree *tree, const char *fname)
165 struct smb_unlink parms;
167 parms.in.pattern = fname;
168 if (strchr(fname, '*')) {
169 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
171 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
174 return smb_raw_unlink(tree, &parms);
177 /****************************************************************************
179 ****************************************************************************/
180 NTSTATUS cli_mkdir(struct cli_tree *tree, const char *dname)
182 union smb_mkdir parms;
184 parms.mkdir.level = RAW_MKDIR_MKDIR;
185 parms.mkdir.in.path = dname;
187 return smb_raw_mkdir(tree, &parms);
191 /****************************************************************************
193 ****************************************************************************/
194 NTSTATUS cli_rmdir(struct cli_tree *tree, const char *dname)
196 struct smb_rmdir parms;
198 parms.in.path = dname;
200 return smb_raw_rmdir(tree, &parms);
204 /****************************************************************************
205 Set or clear the delete on close flag.
206 ****************************************************************************/
207 NTSTATUS cli_nt_delete_on_close(struct cli_tree *tree, int fnum, BOOL flag)
209 union smb_setfileinfo parms;
212 parms.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
213 parms.disposition_info.file.fnum = fnum;
214 parms.disposition_info.in.delete_on_close = flag;
216 status = smb_raw_setfileinfo(tree, &parms);
222 /****************************************************************************
223 Create/open a file - exposing the full horror of the NT API :-).
224 Used in CIFS-on-CIFS NTVFS.
225 ****************************************************************************/
226 int cli_nt_create_full(struct cli_tree *tree, const char *fname,
227 uint32_t CreatFlags, uint32_t DesiredAccess,
228 uint32_t FileAttributes, uint32_t ShareAccess,
229 uint32_t CreateDisposition, uint32_t CreateOptions,
230 uint8_t SecurityFlags)
232 union smb_open open_parms;
236 mem_ctx = talloc_init("raw_open");
237 if (!mem_ctx) return -1;
239 open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
240 open_parms.ntcreatex.in.flags = CreatFlags;
241 open_parms.ntcreatex.in.root_fid = 0;
242 open_parms.ntcreatex.in.access_mask = DesiredAccess;
243 open_parms.ntcreatex.in.file_attr = FileAttributes;
244 open_parms.ntcreatex.in.alloc_size = 0;
245 open_parms.ntcreatex.in.share_access = ShareAccess;
246 open_parms.ntcreatex.in.open_disposition = CreateDisposition;
247 open_parms.ntcreatex.in.create_options = CreateOptions;
248 open_parms.ntcreatex.in.impersonation = 0;
249 open_parms.ntcreatex.in.security_flags = SecurityFlags;
250 open_parms.ntcreatex.in.fname = fname;
252 status = smb_raw_open(tree, mem_ctx, &open_parms);
253 talloc_destroy(mem_ctx);
255 if (NT_STATUS_IS_OK(status)) {
256 return open_parms.ntcreatex.out.fnum;
263 /****************************************************************************
264 Open a file (using SMBopenx)
265 WARNING: if you open with O_WRONLY then getattrE won't work!
266 ****************************************************************************/
267 int cli_open(struct cli_tree *tree, const char *fname, int flags,
270 union smb_open open_parms;
276 mem_ctx = talloc_init("raw_open");
277 if (!mem_ctx) return -1;
279 if (flags & O_CREAT) {
280 openfn |= OPENX_OPEN_FUNC_CREATE;
282 if (!(flags & O_EXCL)) {
283 if (flags & O_TRUNC) {
284 openfn |= OPENX_OPEN_FUNC_TRUNC;
286 openfn |= OPENX_OPEN_FUNC_OPEN;
290 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
292 if ((flags & O_ACCMODE) == O_RDWR) {
293 accessmode |= OPENX_MODE_ACCESS_RDWR;
294 } else if ((flags & O_ACCMODE) == O_WRONLY) {
295 accessmode |= OPENX_MODE_ACCESS_WRITE;
299 if ((flags & O_SYNC) == O_SYNC) {
300 accessmode |= OPENX_MODE_WRITE_THRU;
304 if (share_mode == DENY_FCB) {
305 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
308 open_parms.openx.level = RAW_OPEN_OPENX;
309 open_parms.openx.in.flags = 0;
310 open_parms.openx.in.open_mode = accessmode;
311 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
312 open_parms.openx.in.file_attrs = 0;
313 open_parms.openx.in.write_time = 0;
314 open_parms.openx.in.open_func = openfn;
315 open_parms.openx.in.size = 0;
316 open_parms.openx.in.timeout = 0;
317 open_parms.openx.in.fname = fname;
319 status = smb_raw_open(tree, mem_ctx, &open_parms);
320 talloc_destroy(mem_ctx);
322 if (NT_STATUS_IS_OK(status)) {
323 return open_parms.openx.out.fnum;
330 /****************************************************************************
332 ****************************************************************************/
333 NTSTATUS cli_close(struct cli_tree *tree, int fnum)
335 union smb_close close_parms;
338 close_parms.close.level = RAW_CLOSE_CLOSE;
339 close_parms.close.in.fnum = fnum;
340 close_parms.close.in.write_time = 0;
341 status = smb_raw_close(tree, &close_parms);
345 /****************************************************************************
346 send a lock with a specified locktype
347 this is used for testing LOCKING_ANDX_CANCEL_LOCK
348 ****************************************************************************/
349 NTSTATUS cli_locktype(struct cli_tree *tree, int fnum,
350 uint32_t offset, uint32_t len, int timeout,
353 union smb_lock parms;
354 struct smb_lock_entry lock[1];
357 parms.lockx.level = RAW_LOCK_LOCKX;
358 parms.lockx.in.fnum = fnum;
359 parms.lockx.in.mode = locktype;
360 parms.lockx.in.timeout = timeout;
361 parms.lockx.in.ulock_cnt = 0;
362 parms.lockx.in.lock_cnt = 1;
363 lock[0].pid = tree->session->pid;
364 lock[0].offset = offset;
366 parms.lockx.in.locks = &lock[0];
368 status = smb_raw_lock(tree, &parms);
374 /****************************************************************************
376 ****************************************************************************/
377 NTSTATUS cli_lock(struct cli_tree *tree, int fnum,
378 uint32_t offset, uint32_t len, int timeout,
379 enum brl_type lock_type)
381 union smb_lock parms;
382 struct smb_lock_entry lock[1];
385 parms.lockx.level = RAW_LOCK_LOCKX;
386 parms.lockx.in.fnum = fnum;
387 parms.lockx.in.mode = (lock_type == READ_LOCK? 1 : 0);
388 parms.lockx.in.timeout = timeout;
389 parms.lockx.in.ulock_cnt = 0;
390 parms.lockx.in.lock_cnt = 1;
391 lock[0].pid = tree->session->pid;
392 lock[0].offset = offset;
394 parms.lockx.in.locks = &lock[0];
396 status = smb_raw_lock(tree, &parms);
402 /****************************************************************************
404 ****************************************************************************/
405 NTSTATUS cli_unlock(struct cli_tree *tree, int fnum, uint32_t offset, uint32_t len)
407 union smb_lock parms;
408 struct smb_lock_entry lock[1];
411 parms.lockx.level = RAW_LOCK_LOCKX;
412 parms.lockx.in.fnum = fnum;
413 parms.lockx.in.mode = 0;
414 parms.lockx.in.timeout = 0;
415 parms.lockx.in.ulock_cnt = 1;
416 parms.lockx.in.lock_cnt = 0;
417 lock[0].pid = tree->session->pid;
418 lock[0].offset = offset;
420 parms.lockx.in.locks = &lock[0];
422 status = smb_raw_lock(tree, &parms);
427 /****************************************************************************
428 Lock a file with 64 bit offsets.
429 ****************************************************************************/
430 NTSTATUS cli_lock64(struct cli_tree *tree, int fnum,
431 SMB_OFF_T offset, SMB_OFF_T len, int timeout,
432 enum brl_type lock_type)
434 union smb_lock parms;
436 struct smb_lock_entry lock[1];
439 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
440 return cli_lock(tree, fnum, offset, len, timeout, lock_type);
443 parms.lockx.level = RAW_LOCK_LOCKX;
444 parms.lockx.in.fnum = fnum;
446 ltype = (lock_type == READ_LOCK? 1 : 0);
447 ltype |= LOCKING_ANDX_LARGE_FILES;
448 parms.lockx.in.mode = ltype;
449 parms.lockx.in.timeout = timeout;
450 parms.lockx.in.ulock_cnt = 0;
451 parms.lockx.in.lock_cnt = 1;
452 lock[0].pid = tree->session->pid;
453 lock[0].offset = offset;
455 parms.lockx.in.locks = &lock[0];
457 status = smb_raw_lock(tree, &parms);
463 /****************************************************************************
464 Unlock a file with 64 bit offsets.
465 ****************************************************************************/
466 NTSTATUS cli_unlock64(struct cli_tree *tree, int fnum, SMB_OFF_T offset,
469 union smb_lock parms;
470 struct smb_lock_entry lock[1];
473 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
474 return cli_unlock(tree, fnum, offset, len);
477 parms.lockx.level = RAW_LOCK_LOCKX;
478 parms.lockx.in.fnum = fnum;
479 parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
480 parms.lockx.in.timeout = 0;
481 parms.lockx.in.ulock_cnt = 1;
482 parms.lockx.in.lock_cnt = 0;
483 lock[0].pid = tree->session->pid;
484 lock[0].offset = offset;
486 parms.lockx.in.locks = &lock[0];
488 status = smb_raw_lock(tree, &parms);
494 /****************************************************************************
495 Do a SMBgetattrE call.
496 ****************************************************************************/
497 NTSTATUS cli_getattrE(struct cli_tree *tree, int fnum,
498 uint16_t *attr, size_t *size,
499 time_t *c_time, time_t *a_time, time_t *m_time)
501 union smb_fileinfo parms;
504 parms.getattre.level = RAW_FILEINFO_GETATTRE;
505 parms.getattre.in.fnum = fnum;
507 status = smb_raw_fileinfo(tree, NULL, &parms);
509 if (!NT_STATUS_IS_OK(status))
513 *size = parms.getattre.out.size;
517 *attr = parms.getattre.out.attrib;
521 *c_time = parms.getattre.out.create_time;
525 *a_time = parms.getattre.out.access_time;
529 *m_time = parms.getattre.out.write_time;
535 /****************************************************************************
537 ****************************************************************************/
538 NTSTATUS cli_getatr(struct cli_tree *tree, const char *fname,
539 uint16_t *attr, size_t *size, time_t *t)
541 union smb_fileinfo parms;
544 parms.getattr.level = RAW_FILEINFO_GETATTR;
545 parms.getattr.in.fname = fname;
547 status = smb_raw_pathinfo(tree, NULL, &parms);
549 if (!NT_STATUS_IS_OK(status)) {
554 *size = parms.getattr.out.size;
558 *t = parms.getattr.out.write_time;
562 *attr = parms.getattr.out.attrib;
569 /****************************************************************************
571 ****************************************************************************/
572 NTSTATUS cli_setatr(struct cli_tree *tree, const char *fname, uint16_t mode,
575 union smb_setfileinfo parms;
578 parms.setattr.level = RAW_SFILEINFO_SETATTR;
579 parms.setattr.in.attrib = mode;
580 parms.setattr.in.write_time = t;
581 parms.setattr.file.fname = fname;
583 status = smb_raw_setpathinfo(tree, &parms);
589 /****************************************************************************
590 Check for existence of a dir.
591 ****************************************************************************/
592 NTSTATUS cli_chkpath(struct cli_tree *tree, const char *path)
594 struct smb_chkpath parms;
598 path2 = strdup(path);
599 trim_string(path2,NULL,"\\");
602 path2 = strdup("\\");
605 parms.in.path = path2;
607 status = smb_raw_chkpath(tree, &parms);
615 /****************************************************************************
617 ****************************************************************************/
618 NTSTATUS cli_dskattr(struct cli_tree *tree, int *bsize, int *total, int *avail)
620 union smb_fsinfo fsinfo_parms;
624 mem_ctx = talloc_init("cli_dskattr");
626 fsinfo_parms.dskattr.level = RAW_QFS_DSKATTR;
627 status = smb_raw_fsinfo(tree, mem_ctx, &fsinfo_parms);
628 if (NT_STATUS_IS_OK(status)) {
629 *bsize = fsinfo_parms.dskattr.out.block_size;
630 *total = fsinfo_parms.dskattr.out.units_total;
631 *avail = fsinfo_parms.dskattr.out.units_free;
634 talloc_destroy(mem_ctx);
640 /****************************************************************************
641 Create and open a temporary file.
642 ****************************************************************************/
643 int cli_ctemp(struct cli_tree *tree, const char *path, char **tmp_path)
645 union smb_open open_parms;
649 mem_ctx = talloc_init("raw_open");
650 if (!mem_ctx) return -1;
652 open_parms.openx.level = RAW_OPEN_CTEMP;
653 open_parms.ctemp.in.attrib = 0;
654 open_parms.ctemp.in.directory = path;
655 open_parms.ctemp.in.write_time = 0;
657 status = smb_raw_open(tree, mem_ctx, &open_parms);
659 *tmp_path = strdup(open_parms.ctemp.out.name);
661 talloc_destroy(mem_ctx);
662 if (NT_STATUS_IS_OK(status)) {
663 return open_parms.ctemp.out.fnum;