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 BOOL 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);
48 return NT_STATUS_IS_OK(status);
51 /****************************************************************************
52 Map standard UNIX permissions onto wire representations.
53 ****************************************************************************/
54 static uint32 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 BOOL 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 BOOL 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 BOOL cli_unix_chmod_chown_internal(struct cli_tree *tree,
103 uint32 mode, uint32 uid, uint32 gid)
105 union smb_setfileinfo parms;
108 parms.generic.level = SMB_SFILEINFO_UNIX_BASIC;
109 parms.unix_basic.file.fname = fname;
110 parms.unix_basic.in.uid = uid;
111 parms.unix_basic.in.gid = gid;
112 parms.unix_basic.in.mode = mode;
114 status = smb_raw_setpathinfo(tree, &parms);
116 return NT_STATUS_IS_OK(status);
119 /****************************************************************************
120 chmod a file (UNIX extensions).
121 ****************************************************************************/
123 BOOL cli_unix_chmod(struct cli_tree *tree, const char *fname, mode_t mode)
125 return cli_unix_chmod_chown_internal(tree, fname,
126 unix_perms_to_wire(mode),
131 /****************************************************************************
132 chown a file (UNIX extensions).
133 ****************************************************************************/
134 BOOL cli_unix_chown(struct cli_tree *tree, const char *fname, uid_t uid,
137 return cli_unix_chmod_chown_internal(tree, fname, SMB_MODE_NO_CHANGE,
138 (uint32)uid, (uint32)gid);
142 /****************************************************************************
144 ****************************************************************************/
145 BOOL cli_rename(struct cli_tree *tree, const char *fname_src,
146 const char *fname_dst)
148 union smb_rename parms;
150 parms.generic.level = RAW_RENAME_RENAME;
151 parms.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
152 parms.rename.in.pattern1 = fname_src;
153 parms.rename.in.pattern2 = fname_dst;
154 return NT_STATUS_IS_OK(smb_raw_rename(tree, &parms));
158 /****************************************************************************
160 ****************************************************************************/
161 BOOL cli_unlink(struct cli_tree *tree, const char *fname)
163 struct smb_unlink parms;
165 parms.in.pattern = fname;
166 if (strchr(fname, '*')) {
167 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
169 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
171 return NT_STATUS_IS_OK(smb_raw_unlink(tree, &parms));
174 /****************************************************************************
176 ****************************************************************************/
177 BOOL cli_mkdir(struct cli_tree *tree, const char *dname)
179 union smb_mkdir parms;
181 parms.mkdir.level = RAW_MKDIR_MKDIR;
182 parms.mkdir.in.path = dname;
184 return NT_STATUS_IS_OK(smb_raw_mkdir(tree, &parms));
188 /****************************************************************************
190 ****************************************************************************/
191 BOOL cli_rmdir(struct cli_tree *tree, const char *dname)
193 struct smb_rmdir parms;
195 parms.in.path = dname;
196 return NT_STATUS_IS_OK(smb_raw_rmdir(tree, &parms));
200 /****************************************************************************
201 Set or clear the delete on close flag.
202 ****************************************************************************/
203 BOOL cli_nt_delete_on_close(struct cli_tree *tree, int fnum, BOOL flag)
205 union smb_setfileinfo parms;
208 parms.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
209 parms.disposition_info.file.fnum = fnum;
210 parms.disposition_info.in.delete_on_close = flag;
212 status = smb_raw_setfileinfo(tree, &parms);
214 return NT_STATUS_IS_OK(status);
218 /****************************************************************************
219 Create/open a file - exposing the full horror of the NT API :-).
220 Used in CIFS-on-CIFS NTVFS.
221 ****************************************************************************/
222 int cli_nt_create_full(struct cli_tree *tree, const char *fname,
223 uint32 CreatFlags, uint32 DesiredAccess,
224 uint32 FileAttributes, uint32 ShareAccess,
225 uint32 CreateDisposition, uint32 CreateOptions,
228 union smb_open open_parms;
232 mem_ctx = talloc_init("raw_open");
233 if (!mem_ctx) return -1;
235 open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
236 open_parms.ntcreatex.in.flags = CreatFlags;
237 open_parms.ntcreatex.in.root_fid = 0;
238 open_parms.ntcreatex.in.access_mask = DesiredAccess;
239 open_parms.ntcreatex.in.file_attr = FileAttributes;
240 open_parms.ntcreatex.in.alloc_size = 0;
241 open_parms.ntcreatex.in.share_access = ShareAccess;
242 open_parms.ntcreatex.in.open_disposition = CreateDisposition;
243 open_parms.ntcreatex.in.create_options = CreateOptions;
244 open_parms.ntcreatex.in.impersonation = 0;
245 open_parms.ntcreatex.in.security_flags = SecurityFlags;
246 open_parms.ntcreatex.in.fname = fname;
248 status = smb_raw_open(tree, mem_ctx, &open_parms);
249 talloc_destroy(mem_ctx);
251 if (NT_STATUS_IS_OK(status)) {
252 return open_parms.ntcreatex.out.fnum;
259 /****************************************************************************
260 Open a file (using SMBopenx)
261 WARNING: if you open with O_WRONLY then getattrE won't work!
262 ****************************************************************************/
263 int cli_open(struct cli_tree *tree, const char *fname, int flags,
266 union smb_open open_parms;
268 unsigned accessmode=0;
272 mem_ctx = talloc_init("raw_open");
273 if (!mem_ctx) return -1;
275 if (flags & O_CREAT) {
276 openfn |= OPENX_OPEN_FUNC_CREATE;
278 if (!(flags & O_EXCL)) {
279 if (flags & O_TRUNC) {
280 openfn |= OPENX_OPEN_FUNC_TRUNC;
282 openfn |= OPENX_OPEN_FUNC_OPEN;
286 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
288 if ((flags & O_ACCMODE) == O_RDWR) {
289 accessmode |= OPENX_MODE_ACCESS_RDWR;
290 } else if ((flags & O_ACCMODE) == O_WRONLY) {
291 accessmode |= OPENX_MODE_ACCESS_WRITE;
295 if ((flags & O_SYNC) == O_SYNC) {
296 accessmode |= OPENX_MODE_WRITE_THRU;
300 if (share_mode == DENY_FCB) {
301 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
304 open_parms.openx.level = RAW_OPEN_OPENX;
305 open_parms.openx.in.flags = 0;
306 open_parms.openx.in.open_mode = accessmode;
307 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
308 open_parms.openx.in.file_attrs = 0;
309 open_parms.openx.in.write_time = 0;
310 open_parms.openx.in.open_func = openfn;
311 open_parms.openx.in.size = 0;
312 open_parms.openx.in.timeout = 0;
313 open_parms.openx.in.fname = fname;
315 status = smb_raw_open(tree, mem_ctx, &open_parms);
316 talloc_destroy(mem_ctx);
318 if (NT_STATUS_IS_OK(status)) {
319 return open_parms.openx.out.fnum;
326 /****************************************************************************
328 ****************************************************************************/
329 BOOL cli_close(struct cli_tree *tree, int fnum)
331 union smb_close close_parms;
334 close_parms.close.level = RAW_CLOSE_CLOSE;
335 close_parms.close.in.fnum = fnum;
336 close_parms.close.in.write_time = 0;
337 status = smb_raw_close(tree, &close_parms);
338 return NT_STATUS_IS_OK(status);
341 /****************************************************************************
342 send a lock with a specified locktype
343 this is used for testing LOCKING_ANDX_CANCEL_LOCK
344 ****************************************************************************/
345 NTSTATUS cli_locktype(struct cli_tree *tree, int fnum,
346 uint32 offset, uint32 len, int timeout, unsigned char locktype)
348 union smb_lock parms;
349 struct smb_lock_entry lock[1];
352 parms.lockx.level = RAW_LOCK_LOCKX;
353 parms.lockx.in.fnum = fnum;
354 parms.lockx.in.mode = locktype;
355 parms.lockx.in.timeout = timeout;
356 parms.lockx.in.ulock_cnt = 0;
357 parms.lockx.in.lock_cnt = 1;
358 lock[0].pid = tree->session->pid;
359 lock[0].offset = offset;
361 parms.lockx.in.locks = &lock[0];
363 status = smb_raw_lock(tree, &parms);
369 /****************************************************************************
371 ****************************************************************************/
372 BOOL cli_lock(struct cli_tree *tree, int fnum,
373 uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
375 union smb_lock parms;
376 struct smb_lock_entry lock[1];
379 parms.lockx.level = RAW_LOCK_LOCKX;
380 parms.lockx.in.fnum = fnum;
381 parms.lockx.in.mode = (lock_type == READ_LOCK? 1 : 0);
382 parms.lockx.in.timeout = timeout;
383 parms.lockx.in.ulock_cnt = 0;
384 parms.lockx.in.lock_cnt = 1;
385 lock[0].pid = tree->session->pid;
386 lock[0].offset = offset;
388 parms.lockx.in.locks = &lock[0];
390 status = smb_raw_lock(tree, &parms);
392 return NT_STATUS_IS_OK(status);
396 /****************************************************************************
398 ****************************************************************************/
399 BOOL cli_unlock(struct cli_tree *tree, int fnum, uint32 offset, uint32 len)
401 union smb_lock parms;
402 struct smb_lock_entry lock[1];
405 parms.lockx.level = RAW_LOCK_LOCKX;
406 parms.lockx.in.fnum = fnum;
407 parms.lockx.in.mode = 0;
408 parms.lockx.in.timeout = 0;
409 parms.lockx.in.ulock_cnt = 1;
410 parms.lockx.in.lock_cnt = 0;
411 lock[0].pid = tree->session->pid;
412 lock[0].offset = offset;
414 parms.lockx.in.locks = &lock[0];
416 status = smb_raw_lock(tree, &parms);
417 return NT_STATUS_IS_OK(status);
421 /****************************************************************************
422 Lock a file with 64 bit offsets.
423 ****************************************************************************/
424 BOOL cli_lock64(struct cli_tree *tree, int fnum,
425 SMB_OFF_T offset, SMB_OFF_T len, int timeout, enum brl_type lock_type)
427 union smb_lock parms;
429 struct smb_lock_entry lock[1];
432 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
433 return cli_lock(tree, fnum, offset, len, timeout, lock_type);
436 parms.lockx.level = RAW_LOCK_LOCKX;
437 parms.lockx.in.fnum = fnum;
439 ltype = (lock_type == READ_LOCK? 1 : 0);
440 ltype |= LOCKING_ANDX_LARGE_FILES;
441 parms.lockx.in.mode = ltype;
442 parms.lockx.in.timeout = timeout;
443 parms.lockx.in.ulock_cnt = 0;
444 parms.lockx.in.lock_cnt = 1;
445 lock[0].pid = tree->session->pid;
446 lock[0].offset = offset;
448 parms.lockx.in.locks = &lock[0];
450 status = smb_raw_lock(tree, &parms);
452 return NT_STATUS_IS_OK(status);
456 /****************************************************************************
457 Unlock a file with 64 bit offsets.
458 ****************************************************************************/
459 BOOL cli_unlock64(struct cli_tree *tree, int fnum, SMB_OFF_T offset, SMB_OFF_T len)
461 union smb_lock parms;
462 struct smb_lock_entry lock[1];
465 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
466 return cli_unlock(tree, fnum, offset, len);
469 parms.lockx.level = RAW_LOCK_LOCKX;
470 parms.lockx.in.fnum = fnum;
471 parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
472 parms.lockx.in.timeout = 0;
473 parms.lockx.in.ulock_cnt = 1;
474 parms.lockx.in.lock_cnt = 0;
475 lock[0].pid = tree->session->pid;
476 lock[0].offset = offset;
478 parms.lockx.in.locks = &lock[0];
480 status = smb_raw_lock(tree, &parms);
482 return NT_STATUS_IS_OK(status);
486 /****************************************************************************
487 Do a SMBgetattrE call.
488 ****************************************************************************/
489 BOOL cli_getattrE(struct cli_tree *tree, int fd,
490 uint16 *attr, size_t *size,
491 time_t *c_time, time_t *a_time, time_t *m_time)
493 union smb_fileinfo parms;
496 parms.getattre.level = RAW_FILEINFO_GETATTRE;
497 parms.getattre.in.fnum = fd;
499 status = smb_raw_fileinfo(tree, NULL, &parms);
501 if (!NT_STATUS_IS_OK(status))
505 *size = parms.getattre.out.size;
509 *attr = parms.getattre.out.attrib;
513 *c_time = parms.getattre.out.create_time;
517 *a_time = parms.getattre.out.access_time;
521 *m_time = parms.getattre.out.write_time;
527 /****************************************************************************
529 ****************************************************************************/
530 BOOL cli_getatr(struct cli_tree *tree, const char *fname,
531 uint16 *attr, size_t *size, time_t *t)
533 union smb_fileinfo parms;
536 parms.getattr.level = RAW_FILEINFO_GETATTR;
537 parms.getattr.in.fname = fname;
539 status = smb_raw_pathinfo(tree, NULL, &parms);
541 if (!NT_STATUS_IS_OK(status)) {
546 *size = parms.getattr.out.size;
550 *t = parms.getattr.out.write_time;
554 *attr = parms.getattr.out.attrib;
561 /****************************************************************************
563 ****************************************************************************/
564 BOOL cli_setatr(struct cli_tree *tree, const char *fname, uint16 mode, time_t t)
566 union smb_setfileinfo parms;
569 parms.setattr.level = RAW_SFILEINFO_SETATTR;
570 parms.setattr.in.attrib = mode;
571 parms.setattr.in.write_time = t;
572 parms.setattr.file.fname = fname;
574 status = smb_raw_setpathinfo(tree, &parms);
576 return NT_STATUS_IS_OK(status);
580 /****************************************************************************
581 Check for existence of a dir.
582 ****************************************************************************/
583 BOOL cli_chkpath(struct cli_tree *tree, const char *path)
585 struct smb_chkpath parms;
589 path2 = strdup(path);
590 trim_string(path2,NULL,"\\");
593 path2 = strdup("\\");
596 parms.in.path = path2;
598 status = smb_raw_chkpath(tree, &parms);
602 return NT_STATUS_IS_OK(status);
606 /****************************************************************************
608 ****************************************************************************/
609 BOOL cli_dskattr(struct cli_tree *tree, int *bsize, int *total, int *avail)
611 union smb_fsinfo fsinfo_parms;
615 mem_ctx = talloc_init("cli_dskattr");
617 fsinfo_parms.dskattr.level = RAW_QFS_DSKATTR;
618 status = smb_raw_fsinfo(tree, mem_ctx, &fsinfo_parms);
619 if (NT_STATUS_IS_OK(status)) {
620 *bsize = fsinfo_parms.dskattr.out.block_size;
621 *total = fsinfo_parms.dskattr.out.units_total;
622 *avail = fsinfo_parms.dskattr.out.units_free;
625 talloc_destroy(mem_ctx);
627 return NT_STATUS_IS_OK(status);
631 /****************************************************************************
632 Create and open a temporary file.
633 ****************************************************************************/
634 int cli_ctemp(struct cli_tree *tree, const char *path, char **tmp_path)
636 union smb_open open_parms;
640 mem_ctx = talloc_init("raw_open");
641 if (!mem_ctx) return -1;
643 open_parms.openx.level = RAW_OPEN_CTEMP;
644 open_parms.ctemp.in.attrib = 0;
645 open_parms.ctemp.in.directory = path;
647 status = smb_raw_open(tree, mem_ctx, &open_parms);
649 *tmp_path = strdup(open_parms.ctemp.out.name);
651 talloc_destroy(mem_ctx);
652 if (NT_STATUS_IS_OK(status)) {
653 return open_parms.ctemp.out.fnum;