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_state *cli,
30 const char *fname_src,
31 const char *fname_dst, BOOL hard_link)
33 union smb_setfileinfo parms;
37 parms.generic.level = SMB_SFILEINFO_UNIX_HLINK;
38 parms.unix_hlink.file.fname = fname_src;
39 parms.unix_hlink.in.link_dest = fname_dst;
41 parms.generic.level = SMB_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(cli->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_state *cli, const char *fname_src, const char *fname_dst)
84 return cli_link_internal(cli, fname_src, fname_dst, False);
87 /****************************************************************************
88 Hard a file (UNIX extensions).
89 ****************************************************************************/
90 BOOL cli_unix_hardlink(struct cli_state *cli, const char *fname_src, const char *fname_dst)
92 return cli_link_internal(cli, fname_src, fname_dst, True);
96 /****************************************************************************
97 Chmod or chown a file internal (UNIX extensions).
98 ****************************************************************************/
99 static BOOL cli_unix_chmod_chown_internal(struct cli_state *cli, const char *fname,
100 uint32 mode, uint32 uid, uint32 gid)
102 union smb_setfileinfo parms;
105 parms.generic.level = SMB_SFILEINFO_UNIX_BASIC;
106 parms.unix_basic.file.fname = fname;
107 parms.unix_basic.in.uid = uid;
108 parms.unix_basic.in.gid = gid;
109 parms.unix_basic.in.mode = mode;
111 status = smb_raw_setpathinfo(cli->tree, &parms);
113 return NT_STATUS_IS_OK(status);
116 /****************************************************************************
117 chmod a file (UNIX extensions).
118 ****************************************************************************/
120 BOOL cli_unix_chmod(struct cli_state *cli, const char *fname, mode_t mode)
122 return cli_unix_chmod_chown_internal(cli, fname,
123 unix_perms_to_wire(mode), SMB_UID_NO_CHANGE, SMB_GID_NO_CHANGE);
126 /****************************************************************************
127 chown a file (UNIX extensions).
128 ****************************************************************************/
129 BOOL cli_unix_chown(struct cli_state *cli, const char *fname, uid_t uid, gid_t gid)
131 return cli_unix_chmod_chown_internal(cli, fname, SMB_MODE_NO_CHANGE, (uint32)uid, (uint32)gid);
135 /****************************************************************************
137 ****************************************************************************/
138 BOOL cli_rename(struct cli_state *cli, const char *fname_src, const char *fname_dst)
140 union smb_rename parms;
142 parms.generic.level = RAW_RENAME_RENAME;
143 parms.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
144 parms.rename.in.pattern1 = fname_src;
145 parms.rename.in.pattern2 = fname_dst;
146 return NT_STATUS_IS_OK(smb_raw_rename(cli->tree, &parms));
150 /****************************************************************************
152 ****************************************************************************/
153 BOOL cli_unlink(struct cli_state *cli, const char *fname)
155 struct smb_unlink parms;
157 parms.in.pattern = fname;
158 if (strchr(fname, '*')) {
159 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
161 parms.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
163 return NT_STATUS_IS_OK(smb_raw_unlink(cli->tree, &parms));
166 /****************************************************************************
168 ****************************************************************************/
169 BOOL cli_mkdir(struct cli_state *cli, const char *dname)
171 union smb_mkdir parms;
173 parms.mkdir.level = RAW_MKDIR_MKDIR;
174 parms.mkdir.in.path = dname;
176 return NT_STATUS_IS_OK(smb_raw_mkdir(cli->tree, &parms));
180 /****************************************************************************
182 ****************************************************************************/
183 BOOL cli_rmdir(struct cli_state *cli, const char *dname)
185 struct smb_rmdir parms;
187 parms.in.path = dname;
188 return NT_STATUS_IS_OK(smb_raw_rmdir(cli->tree, &parms));
192 /****************************************************************************
193 Set or clear the delete on close flag.
194 ****************************************************************************/
195 BOOL cli_nt_delete_on_close(struct cli_state *cli, int fnum, BOOL flag)
197 union smb_setfileinfo parms;
200 parms.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
201 parms.disposition_info.file.fnum = fnum;
202 parms.disposition_info.in.delete_on_close = flag;
204 status = smb_raw_setfileinfo(cli->tree, &parms);
206 return NT_STATUS_IS_OK(status);
210 /****************************************************************************
211 Create/open a file - exposing the full horror of the NT API :-).
212 Used in CIFS-on-CIFS NTVFS.
213 ****************************************************************************/
214 int cli_nt_create_full(struct cli_state *cli, const char *fname,
215 uint32 CreatFlags, uint32 DesiredAccess,
216 uint32 FileAttributes, uint32 ShareAccess,
217 uint32 CreateDisposition, uint32 CreateOptions,
220 union smb_open open_parms;
224 mem_ctx = talloc_init("raw_open");
225 if (!mem_ctx) return -1;
227 open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
228 open_parms.ntcreatex.in.flags = CreatFlags;
229 open_parms.ntcreatex.in.root_fid = 0;
230 open_parms.ntcreatex.in.access_mask = DesiredAccess;
231 open_parms.ntcreatex.in.file_attr = FileAttributes;
232 open_parms.ntcreatex.in.alloc_size = 0;
233 open_parms.ntcreatex.in.share_access = ShareAccess;
234 open_parms.ntcreatex.in.open_disposition = CreateDisposition;
235 open_parms.ntcreatex.in.create_options = CreateOptions;
236 open_parms.ntcreatex.in.impersonation = 0;
237 open_parms.ntcreatex.in.security_flags = SecurityFlags;
238 open_parms.ntcreatex.in.fname = fname;
240 status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
241 talloc_destroy(mem_ctx);
243 if (NT_STATUS_IS_OK(status)) {
244 return open_parms.ntcreatex.out.fnum;
251 /****************************************************************************
252 Open a file (using SMBopenx)
253 WARNING: if you open with O_WRONLY then getattrE won't work!
254 ****************************************************************************/
255 int cli_open(struct cli_state *cli, const char *fname, int flags, int share_mode)
257 union smb_open open_parms;
259 unsigned accessmode=0;
263 mem_ctx = talloc_init("raw_open");
264 if (!mem_ctx) return -1;
266 if (flags & O_CREAT) {
267 openfn |= OPENX_OPEN_FUNC_CREATE;
269 if (!(flags & O_EXCL)) {
270 if (flags & O_TRUNC) {
271 openfn |= OPENX_OPEN_FUNC_TRUNC;
273 openfn |= OPENX_OPEN_FUNC_OPEN;
277 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
279 if ((flags & O_ACCMODE) == O_RDWR) {
280 accessmode |= OPENX_MODE_ACCESS_RDWR;
281 } else if ((flags & O_ACCMODE) == O_WRONLY) {
282 accessmode |= OPENX_MODE_ACCESS_WRITE;
286 if ((flags & O_SYNC) == O_SYNC) {
287 accessmode |= OPENX_MODE_WRITE_THRU;
291 if (share_mode == DENY_FCB) {
292 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
295 open_parms.openx.level = RAW_OPEN_OPENX;
296 open_parms.openx.in.flags = 0;
297 open_parms.openx.in.open_mode = accessmode;
298 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
299 open_parms.openx.in.file_attrs = 0;
300 open_parms.openx.in.write_time = 0;
301 open_parms.openx.in.open_func = openfn;
302 open_parms.openx.in.size = 0;
303 open_parms.openx.in.timeout = 0;
304 open_parms.openx.in.fname = fname;
306 status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
307 talloc_destroy(mem_ctx);
309 if (NT_STATUS_IS_OK(status)) {
310 return open_parms.openx.out.fnum;
317 /****************************************************************************
319 ****************************************************************************/
320 BOOL cli_close(struct cli_state *cli, int fnum)
322 union smb_close close_parms;
325 close_parms.close.level = RAW_CLOSE_CLOSE;
326 close_parms.close.in.fnum = fnum;
327 close_parms.close.in.write_time = 0;
328 status = smb_raw_close(cli->tree, &close_parms);
329 return NT_STATUS_IS_OK(status);
332 /****************************************************************************
333 send a lock with a specified locktype
334 this is used for testing LOCKING_ANDX_CANCEL_LOCK
335 ****************************************************************************/
336 NTSTATUS cli_locktype(struct cli_state *cli, int fnum,
337 uint32 offset, uint32 len, int timeout, unsigned char locktype)
339 union smb_lock parms;
340 struct smb_lock_entry lock[1];
343 parms.lockx.level = RAW_LOCK_LOCKX;
344 parms.lockx.in.fnum = fnum;
345 parms.lockx.in.mode = locktype;
346 parms.lockx.in.timeout = timeout;
347 parms.lockx.in.ulock_cnt = 0;
348 parms.lockx.in.lock_cnt = 1;
349 lock[0].pid = cli->session->pid;
350 lock[0].offset = offset;
352 parms.lockx.in.locks = &lock[0];
354 status = smb_raw_lock(cli->tree, &parms);
360 /****************************************************************************
362 ****************************************************************************/
363 BOOL cli_lock(struct cli_state *cli, int fnum,
364 uint32 offset, uint32 len, int timeout, enum brl_type lock_type)
366 union smb_lock parms;
367 struct smb_lock_entry lock[1];
370 parms.lockx.level = RAW_LOCK_LOCKX;
371 parms.lockx.in.fnum = fnum;
372 parms.lockx.in.mode = (lock_type == READ_LOCK? 1 : 0);
373 parms.lockx.in.timeout = timeout;
374 parms.lockx.in.ulock_cnt = 0;
375 parms.lockx.in.lock_cnt = 1;
376 lock[0].pid = cli->session->pid;
377 lock[0].offset = offset;
379 parms.lockx.in.locks = &lock[0];
381 status = smb_raw_lock(cli->tree, &parms);
383 return NT_STATUS_IS_OK(status);
387 /****************************************************************************
389 ****************************************************************************/
390 BOOL cli_unlock(struct cli_state *cli, int fnum, uint32 offset, uint32 len)
392 union smb_lock parms;
393 struct smb_lock_entry lock[1];
396 parms.lockx.level = RAW_LOCK_LOCKX;
397 parms.lockx.in.fnum = fnum;
398 parms.lockx.in.mode = 0;
399 parms.lockx.in.timeout = 0;
400 parms.lockx.in.ulock_cnt = 1;
401 parms.lockx.in.lock_cnt = 0;
402 lock[0].pid = cli->session->pid;
403 lock[0].offset = offset;
405 parms.lockx.in.locks = &lock[0];
407 status = smb_raw_lock(cli->tree, &parms);
408 return NT_STATUS_IS_OK(status);
412 /****************************************************************************
413 Lock a file with 64 bit offsets.
414 ****************************************************************************/
415 BOOL cli_lock64(struct cli_state *cli, int fnum,
416 SMB_OFF_T offset, SMB_OFF_T len, int timeout, enum brl_type lock_type)
418 union smb_lock parms;
420 struct smb_lock_entry lock[1];
423 if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
424 return cli_lock(cli, fnum, offset, len, timeout, lock_type);
427 parms.lockx.level = RAW_LOCK_LOCKX;
428 parms.lockx.in.fnum = fnum;
430 ltype = (lock_type == READ_LOCK? 1 : 0);
431 ltype |= LOCKING_ANDX_LARGE_FILES;
432 parms.lockx.in.mode = ltype;
433 parms.lockx.in.timeout = timeout;
434 parms.lockx.in.ulock_cnt = 0;
435 parms.lockx.in.lock_cnt = 1;
436 lock[0].pid = cli->session->pid;
437 lock[0].offset = offset;
439 parms.lockx.in.locks = &lock[0];
441 status = smb_raw_lock(cli->tree, &parms);
443 return NT_STATUS_IS_OK(status);
447 /****************************************************************************
448 Unlock a file with 64 bit offsets.
449 ****************************************************************************/
450 BOOL cli_unlock64(struct cli_state *cli, int fnum, SMB_OFF_T offset, SMB_OFF_T len)
452 union smb_lock parms;
453 struct smb_lock_entry lock[1];
456 if (!(cli->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
457 return cli_unlock(cli, fnum, offset, len);
460 parms.lockx.level = RAW_LOCK_LOCKX;
461 parms.lockx.in.fnum = fnum;
462 parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
463 parms.lockx.in.timeout = 0;
464 parms.lockx.in.ulock_cnt = 1;
465 parms.lockx.in.lock_cnt = 0;
466 lock[0].pid = cli->session->pid;
467 lock[0].offset = offset;
469 parms.lockx.in.locks = &lock[0];
471 status = smb_raw_lock(cli->tree, &parms);
473 return NT_STATUS_IS_OK(status);
477 /****************************************************************************
478 Do a SMBgetattrE call.
479 ****************************************************************************/
480 BOOL cli_getattrE(struct cli_state *cli, int fd,
481 uint16 *attr, size_t *size,
482 time_t *c_time, time_t *a_time, time_t *m_time)
484 union smb_fileinfo parms;
487 parms.getattre.level = RAW_FILEINFO_GETATTRE;
488 parms.getattre.in.fnum = fd;
490 status = smb_raw_fileinfo(cli->tree, NULL, &parms);
492 if (!NT_STATUS_IS_OK(status))
496 *size = parms.getattre.out.size;
500 *attr = parms.getattre.out.attrib;
504 *c_time = parms.getattre.out.create_time;
508 *a_time = &parms.getattre.out.access_time;
512 *m_time = &parms.getattre.out.write_time;
518 /****************************************************************************
520 ****************************************************************************/
521 BOOL cli_getatr(struct cli_state *cli, const char *fname,
522 uint16 *attr, size_t *size, time_t *t)
524 union smb_fileinfo parms;
527 parms.getattr.level = RAW_FILEINFO_GETATTR;
528 parms.getattr.in.fname = fname;
530 status = smb_raw_pathinfo(cli->tree, NULL, &parms);
532 if (!NT_STATUS_IS_OK(status)) {
537 *size = parms.getattr.out.size;
541 *t = parms.getattr.out.write_time;
545 *attr = parms.getattr.out.attrib;
552 /****************************************************************************
554 ****************************************************************************/
555 BOOL cli_setatr(struct cli_state *cli, const char *fname, uint16 mode, time_t t)
557 union smb_setfileinfo parms;
560 parms.setattr.level = RAW_SFILEINFO_SETATTR;
561 parms.setattr.in.attrib = mode;
562 parms.setattr.in.write_time = t;
563 parms.setattr.file.fname = fname;
565 status = smb_raw_setpathinfo(cli->tree, &parms);
567 return NT_STATUS_IS_OK(status);
571 /****************************************************************************
572 Check for existence of a dir.
573 ****************************************************************************/
574 BOOL cli_chkpath(struct cli_state *cli, const char *path)
576 struct smb_chkpath parms;
580 path2 = strdup(path);
581 trim_string(path2,NULL,"\\");
584 path2 = strdup("\\");
587 parms.in.path = path2;
589 status = smb_raw_chkpath(cli->tree, &parms);
593 return NT_STATUS_IS_OK(status);
597 /****************************************************************************
599 ****************************************************************************/
600 BOOL cli_dskattr(struct cli_state *cli, int *bsize, int *total, int *avail)
602 union smb_fsinfo fsinfo_parms;
606 mem_ctx = talloc_init("cli_dskattr");
608 fsinfo_parms.dskattr.level = RAW_QFS_DSKATTR;
609 status = smb_raw_fsinfo(cli->tree, mem_ctx, &fsinfo_parms);
610 if (NT_STATUS_IS_OK(status)) {
611 *bsize = fsinfo_parms.dskattr.out.block_size;
612 *total = fsinfo_parms.dskattr.out.units_total;
613 *avail = fsinfo_parms.dskattr.out.units_free;
616 talloc_destroy(mem_ctx);
618 return NT_STATUS_IS_OK(status);
622 /****************************************************************************
623 Create and open a temporary file.
624 ****************************************************************************/
625 int cli_ctemp(struct cli_state *cli, const char *path, char **tmp_path)
627 union smb_open open_parms;
631 mem_ctx = talloc_init("raw_open");
632 if (!mem_ctx) return -1;
634 open_parms.openx.level = RAW_OPEN_CTEMP;
635 open_parms.ctemp.in.attrib = 0;
636 open_parms.ctemp.in.directory = path;
638 status = smb_raw_open(cli->tree, mem_ctx, &open_parms);
640 *tmp_path = strdup(open_parms.ctemp.out.name);
642 talloc_destroy(mem_ctx);
643 if (NT_STATUS_IS_OK(status)) {
644 return open_parms.ctemp.out.fnum;