source: vendor/current/source4/libcli/clifile.c

Last change on this file was 988, checked in by Silvan Scherrer, 9 years ago

Samba Server: update vendor to version 4.4.3

File size: 19.3 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 client file operations
4 Copyright (C) Andrew Tridgell 1994-1998
5 Copyright (C) Jeremy Allison 2001-2002
6 Copyright (C) James Myers 2003
7
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 3 of the License, or
11 (at your option) any later version.
12
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.
17
18 You should have received a copy of the GNU General Public License
19 along with this program. If not, see <http://www.gnu.org/licenses/>.
20*/
21
22#include "includes.h"
23#include "system/filesys.h"
24#include "libcli/raw/libcliraw.h"
25#include "libcli/libcli.h"
26
27/****************************************************************************
28 Hard/Symlink a file (UNIX extensions).
29****************************************************************************/
30
31static NTSTATUS smbcli_link_internal(struct smbcli_tree *tree,
32 const char *fname_src,
33 const char *fname_dst, bool hard_link)
34{
35 union smb_setfileinfo parms;
36 NTSTATUS status;
37
38 if (hard_link) {
39 parms.generic.level = RAW_SFILEINFO_UNIX_HLINK;
40 parms.unix_hlink.in.file.path = fname_src;
41 parms.unix_hlink.in.link_dest = fname_dst;
42 } else {
43 parms.generic.level = RAW_SFILEINFO_UNIX_LINK;
44 parms.unix_link.in.file.path = fname_src;
45 parms.unix_link.in.link_dest = fname_dst;
46 }
47
48 status = smb_raw_setpathinfo(tree, &parms);
49
50 return status;
51}
52
53/****************************************************************************
54 Symlink a file (UNIX extensions).
55****************************************************************************/
56NTSTATUS smbcli_unix_symlink(struct smbcli_tree *tree, const char *fname_src,
57 const char *fname_dst)
58{
59 return smbcli_link_internal(tree, fname_src, fname_dst, false);
60}
61
62/****************************************************************************
63 Hard a file (UNIX extensions).
64****************************************************************************/
65NTSTATUS smbcli_unix_hardlink(struct smbcli_tree *tree, const char *fname_src,
66 const char *fname_dst)
67{
68 return smbcli_link_internal(tree, fname_src, fname_dst, true);
69}
70
71
72/****************************************************************************
73 Chmod or chown a file internal (UNIX extensions).
74****************************************************************************/
75static NTSTATUS smbcli_unix_chmod_chown_internal(struct smbcli_tree *tree,
76 const char *fname,
77 uint32_t mode, uint32_t uid,
78 uint32_t gid)
79{
80 union smb_setfileinfo parms;
81 NTSTATUS status;
82
83 parms.generic.level = SMB_SFILEINFO_UNIX_BASIC;
84 parms.unix_basic.in.file.path = fname;
85 parms.unix_basic.in.uid = uid;
86 parms.unix_basic.in.gid = gid;
87 parms.unix_basic.in.mode = mode;
88
89 status = smb_raw_setpathinfo(tree, &parms);
90
91 return status;
92}
93
94/****************************************************************************
95 chmod a file (UNIX extensions).
96****************************************************************************/
97
98NTSTATUS smbcli_unix_chmod(struct smbcli_tree *tree, const char *fname, mode_t mode)
99{
100 return smbcli_unix_chmod_chown_internal(tree, fname,
101 unix_perms_to_wire(mode),
102 SMB_UID_NO_CHANGE,
103 SMB_GID_NO_CHANGE);
104}
105
106/****************************************************************************
107 chown a file (UNIX extensions).
108****************************************************************************/
109NTSTATUS smbcli_unix_chown(struct smbcli_tree *tree, const char *fname, uid_t uid,
110 gid_t gid)
111{
112 return smbcli_unix_chmod_chown_internal(tree, fname, SMB_MODE_NO_CHANGE,
113 (uint32_t)uid, (uint32_t)gid);
114}
115
116
117/****************************************************************************
118 Rename a file.
119****************************************************************************/
120NTSTATUS smbcli_rename(struct smbcli_tree *tree, const char *fname_src,
121 const char *fname_dst)
122{
123 union smb_rename parms;
124
125 parms.generic.level = RAW_RENAME_RENAME;
126 parms.rename.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
127 parms.rename.in.pattern1 = fname_src;
128 parms.rename.in.pattern2 = fname_dst;
129
130 return smb_raw_rename(tree, &parms);
131}
132
133
134/****************************************************************************
135 Delete a file.
136****************************************************************************/
137NTSTATUS smbcli_unlink(struct smbcli_tree *tree, const char *fname)
138{
139 union smb_unlink parms;
140
141 parms.unlink.in.pattern = fname;
142 if (strchr(fname, '*')) {
143 parms.unlink.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
144 } else {
145 parms.unlink.in.attrib = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_DIRECTORY;
146 }
147
148 return smb_raw_unlink(tree, &parms);
149}
150
151/****************************************************************************
152 Create a directory.
153****************************************************************************/
154NTSTATUS smbcli_mkdir(struct smbcli_tree *tree, const char *dname)
155{
156 union smb_mkdir parms;
157
158 parms.mkdir.level = RAW_MKDIR_MKDIR;
159 parms.mkdir.in.path = dname;
160
161 return smb_raw_mkdir(tree, &parms);
162}
163
164
165/****************************************************************************
166 Remove a directory.
167****************************************************************************/
168NTSTATUS smbcli_rmdir(struct smbcli_tree *tree, const char *dname)
169{
170 struct smb_rmdir parms;
171
172 parms.in.path = dname;
173
174 return smb_raw_rmdir(tree, &parms);
175}
176
177
178/****************************************************************************
179 Set or clear the delete on close flag.
180****************************************************************************/
181NTSTATUS smbcli_nt_delete_on_close(struct smbcli_tree *tree, int fnum,
182 bool flag)
183{
184 union smb_setfileinfo parms;
185 NTSTATUS status;
186
187 parms.disposition_info.level = RAW_SFILEINFO_DISPOSITION_INFO;
188 parms.disposition_info.in.file.fnum = fnum;
189 parms.disposition_info.in.delete_on_close = flag;
190
191 status = smb_raw_setfileinfo(tree, &parms);
192
193 return status;
194}
195
196
197/****************************************************************************
198 Create/open a file - exposing the full horror of the NT API :-).
199 Used in CIFS-on-CIFS NTVFS.
200****************************************************************************/
201int smbcli_nt_create_full(struct smbcli_tree *tree, const char *fname,
202 uint32_t CreatFlags, uint32_t DesiredAccess,
203 uint32_t FileAttributes, uint32_t ShareAccess,
204 uint32_t CreateDisposition, uint32_t CreateOptions,
205 uint8_t SecurityFlags)
206{
207 union smb_open open_parms;
208 TALLOC_CTX *mem_ctx;
209 NTSTATUS status;
210
211 mem_ctx = talloc_init("raw_open");
212 if (!mem_ctx) return -1;
213
214 open_parms.ntcreatex.level = RAW_OPEN_NTCREATEX;
215 open_parms.ntcreatex.in.flags = CreatFlags;
216 open_parms.ntcreatex.in.root_fid.fnum = 0;
217 open_parms.ntcreatex.in.access_mask = DesiredAccess;
218 open_parms.ntcreatex.in.file_attr = FileAttributes;
219 open_parms.ntcreatex.in.alloc_size = 0;
220 open_parms.ntcreatex.in.share_access = ShareAccess;
221 open_parms.ntcreatex.in.open_disposition = CreateDisposition;
222 open_parms.ntcreatex.in.create_options = CreateOptions;
223 open_parms.ntcreatex.in.impersonation = 0;
224 open_parms.ntcreatex.in.security_flags = SecurityFlags;
225 open_parms.ntcreatex.in.fname = fname;
226
227 status = smb_raw_open(tree, mem_ctx, &open_parms);
228 talloc_free(mem_ctx);
229
230 if (NT_STATUS_IS_OK(status)) {
231 return open_parms.ntcreatex.out.file.fnum;
232 }
233
234 return -1;
235}
236
237
238/****************************************************************************
239 Open a file (using SMBopenx)
240 WARNING: if you open with O_WRONLY then getattrE won't work!
241****************************************************************************/
242int smbcli_open(struct smbcli_tree *tree, const char *fname, int flags,
243 int share_mode)
244{
245 union smb_open open_parms;
246 unsigned int openfn=0;
247 unsigned int accessmode=0;
248 TALLOC_CTX *mem_ctx;
249 NTSTATUS status;
250
251 mem_ctx = talloc_init("raw_open");
252 if (!mem_ctx) return -1;
253
254 if (flags & O_CREAT) {
255 openfn |= OPENX_OPEN_FUNC_CREATE;
256 }
257 if (!(flags & O_EXCL)) {
258 if (flags & O_TRUNC) {
259 openfn |= OPENX_OPEN_FUNC_TRUNC;
260 } else {
261 openfn |= OPENX_OPEN_FUNC_OPEN;
262 }
263 }
264
265 accessmode = (share_mode<<OPENX_MODE_DENY_SHIFT);
266
267 if ((flags & O_ACCMODE) == O_RDWR) {
268 accessmode |= OPENX_MODE_ACCESS_RDWR;
269 } else if ((flags & O_ACCMODE) == O_WRONLY) {
270 accessmode |= OPENX_MODE_ACCESS_WRITE;
271 }
272
273#if defined(O_SYNC)
274 if ((flags & O_SYNC) == O_SYNC) {
275 accessmode |= OPENX_MODE_WRITE_THRU;
276 }
277#endif
278
279 if (share_mode == DENY_FCB) {
280 accessmode = OPENX_MODE_ACCESS_FCB | OPENX_MODE_DENY_FCB;
281 }
282
283 open_parms.openx.level = RAW_OPEN_OPENX;
284 open_parms.openx.in.flags = 0;
285 open_parms.openx.in.open_mode = accessmode;
286 open_parms.openx.in.search_attrs = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
287 open_parms.openx.in.file_attrs = 0;
288 open_parms.openx.in.write_time = 0;
289 open_parms.openx.in.open_func = openfn;
290 open_parms.openx.in.size = 0;
291 open_parms.openx.in.timeout = 0;
292 open_parms.openx.in.fname = fname;
293
294 status = smb_raw_open(tree, mem_ctx, &open_parms);
295 talloc_free(mem_ctx);
296
297 if (NT_STATUS_IS_OK(status)) {
298 return open_parms.openx.out.file.fnum;
299 }
300
301 return -1;
302}
303
304
305/****************************************************************************
306 Close a file.
307****************************************************************************/
308NTSTATUS smbcli_close(struct smbcli_tree *tree, int fnum)
309{
310 union smb_close close_parms;
311 NTSTATUS status;
312
313 close_parms.close.level = RAW_CLOSE_CLOSE;
314 close_parms.close.in.file.fnum = fnum;
315 close_parms.close.in.write_time = 0;
316 status = smb_raw_close(tree, &close_parms);
317 return status;
318}
319
320/****************************************************************************
321 send a lock with a specified locktype
322 this is used for testing LOCKING_ANDX_CANCEL_LOCK
323****************************************************************************/
324NTSTATUS smbcli_locktype(struct smbcli_tree *tree, int fnum,
325 uint32_t offset, uint32_t len, int timeout,
326 uint8_t locktype)
327{
328 union smb_lock parms;
329 struct smb_lock_entry lock[1];
330 NTSTATUS status;
331
332 parms.lockx.level = RAW_LOCK_LOCKX;
333 parms.lockx.in.file.fnum = fnum;
334 parms.lockx.in.mode = locktype;
335 parms.lockx.in.timeout = timeout;
336 parms.lockx.in.ulock_cnt = 0;
337 parms.lockx.in.lock_cnt = 1;
338 lock[0].pid = tree->session->pid;
339 lock[0].offset = offset;
340 lock[0].count = len;
341 parms.lockx.in.locks = &lock[0];
342
343 status = smb_raw_lock(tree, &parms);
344
345 return status;
346}
347
348
349/****************************************************************************
350 Lock a file.
351****************************************************************************/
352NTSTATUS smbcli_lock(struct smbcli_tree *tree, int fnum,
353 uint32_t offset, uint32_t len, int timeout,
354 enum brl_type lock_type)
355{
356 union smb_lock parms;
357 struct smb_lock_entry lock[1];
358 NTSTATUS status;
359
360 parms.lockx.level = RAW_LOCK_LOCKX;
361 parms.lockx.in.file.fnum = fnum;
362 parms.lockx.in.mode = (lock_type == READ_LOCK? 1 : 0);
363 parms.lockx.in.timeout = timeout;
364 parms.lockx.in.ulock_cnt = 0;
365 parms.lockx.in.lock_cnt = 1;
366 lock[0].pid = tree->session->pid;
367 lock[0].offset = offset;
368 lock[0].count = len;
369 parms.lockx.in.locks = &lock[0];
370
371 status = smb_raw_lock(tree, &parms);
372
373 return status;
374}
375
376
377/****************************************************************************
378 Unlock a file.
379****************************************************************************/
380NTSTATUS smbcli_unlock(struct smbcli_tree *tree, int fnum, uint32_t offset, uint32_t len)
381{
382 union smb_lock parms;
383 struct smb_lock_entry lock[1];
384 NTSTATUS status;
385
386 parms.lockx.level = RAW_LOCK_LOCKX;
387 parms.lockx.in.file.fnum = fnum;
388 parms.lockx.in.mode = 0;
389 parms.lockx.in.timeout = 0;
390 parms.lockx.in.ulock_cnt = 1;
391 parms.lockx.in.lock_cnt = 0;
392 lock[0].pid = tree->session->pid;
393 lock[0].offset = offset;
394 lock[0].count = len;
395 parms.lockx.in.locks = &lock[0];
396
397 status = smb_raw_lock(tree, &parms);
398 return status;
399}
400
401
402/****************************************************************************
403 Lock a file with 64 bit offsets.
404****************************************************************************/
405NTSTATUS smbcli_lock64(struct smbcli_tree *tree, int fnum,
406 off_t offset, off_t len, int timeout,
407 enum brl_type lock_type)
408{
409 union smb_lock parms;
410 int ltype;
411 struct smb_lock_entry lock[1];
412 NTSTATUS status;
413
414 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
415 return smbcli_lock(tree, fnum, offset, len, timeout, lock_type);
416 }
417
418 parms.lockx.level = RAW_LOCK_LOCKX;
419 parms.lockx.in.file.fnum = fnum;
420
421 ltype = (lock_type == READ_LOCK? 1 : 0);
422 ltype |= LOCKING_ANDX_LARGE_FILES;
423 parms.lockx.in.mode = ltype;
424 parms.lockx.in.timeout = timeout;
425 parms.lockx.in.ulock_cnt = 0;
426 parms.lockx.in.lock_cnt = 1;
427 lock[0].pid = tree->session->pid;
428 lock[0].offset = offset;
429 lock[0].count = len;
430 parms.lockx.in.locks = &lock[0];
431
432 status = smb_raw_lock(tree, &parms);
433
434 return status;
435}
436
437
438/****************************************************************************
439 Unlock a file with 64 bit offsets.
440****************************************************************************/
441NTSTATUS smbcli_unlock64(struct smbcli_tree *tree, int fnum, off_t offset,
442 off_t len)
443{
444 union smb_lock parms;
445 struct smb_lock_entry lock[1];
446 NTSTATUS status;
447
448 if (!(tree->session->transport->negotiate.capabilities & CAP_LARGE_FILES)) {
449 return smbcli_unlock(tree, fnum, offset, len);
450 }
451
452 parms.lockx.level = RAW_LOCK_LOCKX;
453 parms.lockx.in.file.fnum = fnum;
454 parms.lockx.in.mode = LOCKING_ANDX_LARGE_FILES;
455 parms.lockx.in.timeout = 0;
456 parms.lockx.in.ulock_cnt = 1;
457 parms.lockx.in.lock_cnt = 0;
458 lock[0].pid = tree->session->pid;
459 lock[0].offset = offset;
460 lock[0].count = len;
461 parms.lockx.in.locks = &lock[0];
462
463 status = smb_raw_lock(tree, &parms);
464
465 return status;
466}
467
468
469/****************************************************************************
470 Do a SMBgetattrE call.
471****************************************************************************/
472NTSTATUS smbcli_getattrE(struct smbcli_tree *tree, int fnum,
473 uint16_t *attr, size_t *size,
474 time_t *c_time, time_t *a_time, time_t *m_time)
475{
476 union smb_fileinfo parms;
477 NTSTATUS status;
478
479 parms.getattre.level = RAW_FILEINFO_GETATTRE;
480 parms.getattre.in.file.fnum = fnum;
481
482 status = smb_raw_fileinfo(tree, NULL, &parms);
483
484 if (!NT_STATUS_IS_OK(status))
485 return status;
486
487 if (size) {
488 *size = parms.getattre.out.size;
489 }
490
491 if (attr) {
492 *attr = parms.getattre.out.attrib;
493 }
494
495 if (c_time) {
496 *c_time = parms.getattre.out.create_time;
497 }
498
499 if (a_time) {
500 *a_time = parms.getattre.out.access_time;
501 }
502
503 if (m_time) {
504 *m_time = parms.getattre.out.write_time;
505 }
506
507 return status;
508}
509
510/****************************************************************************
511 Do a SMBgetatr call
512****************************************************************************/
513NTSTATUS smbcli_getatr(struct smbcli_tree *tree, const char *fname,
514 uint16_t *attr, size_t *size, time_t *t)
515{
516 union smb_fileinfo parms;
517 NTSTATUS status;
518
519 parms.getattr.level = RAW_FILEINFO_GETATTR;
520 parms.getattr.in.file.path = fname;
521
522 status = smb_raw_pathinfo(tree, NULL, &parms);
523
524 if (!NT_STATUS_IS_OK(status)) {
525 return status;
526 }
527
528 if (size) {
529 *size = parms.getattr.out.size;
530 }
531
532 if (t) {
533 *t = parms.getattr.out.write_time;
534 }
535
536 if (attr) {
537 *attr = parms.getattr.out.attrib;
538 }
539
540 return status;
541}
542
543
544/****************************************************************************
545 Do a SMBsetatr call.
546****************************************************************************/
547NTSTATUS smbcli_setatr(struct smbcli_tree *tree, const char *fname, uint16_t mode,
548 time_t t)
549{
550 union smb_setfileinfo parms;
551
552 parms.setattr.level = RAW_SFILEINFO_SETATTR;
553 parms.setattr.in.file.path = fname;
554 parms.setattr.in.attrib = mode;
555 parms.setattr.in.write_time = t;
556
557 return smb_raw_setpathinfo(tree, &parms);
558}
559
560/****************************************************************************
561 Do a setfileinfo basic_info call.
562****************************************************************************/
563NTSTATUS smbcli_fsetatr(struct smbcli_tree *tree, int fnum, uint16_t mode,
564 NTTIME create_time, NTTIME access_time,
565 NTTIME write_time, NTTIME change_time)
566{
567 union smb_setfileinfo parms;
568
569 parms.basic_info.level = RAW_SFILEINFO_BASIC_INFO;
570 parms.basic_info.in.file.fnum = fnum;
571 parms.basic_info.in.attrib = mode;
572 parms.basic_info.in.create_time = create_time;
573 parms.basic_info.in.access_time = access_time;
574 parms.basic_info.in.write_time = write_time;
575 parms.basic_info.in.change_time = change_time;
576
577 return smb_raw_setfileinfo(tree, &parms);
578}
579
580
581/****************************************************************************
582 truncate a file to a given size
583****************************************************************************/
584NTSTATUS smbcli_ftruncate(struct smbcli_tree *tree, int fnum, uint64_t size)
585{
586 union smb_setfileinfo parms;
587
588 parms.end_of_file_info.level = RAW_SFILEINFO_END_OF_FILE_INFO;
589 parms.end_of_file_info.in.file.fnum = fnum;
590 parms.end_of_file_info.in.size = size;
591
592 return smb_raw_setfileinfo(tree, &parms);
593}
594
595
596/****************************************************************************
597 Check for existence of a dir.
598****************************************************************************/
599NTSTATUS smbcli_chkpath(struct smbcli_tree *tree, const char *path)
600{
601 union smb_chkpath parms;
602 char *path2;
603 NTSTATUS status;
604
605 path2 = strdup(path);
606 trim_string(path2,NULL,"\\");
607 if (!*path2) {
608 free(path2);
609 path2 = strdup("\\");
610 }
611
612 parms.chkpath.in.path = path2;
613
614 status = smb_raw_chkpath(tree, &parms);
615
616 free(path2);
617
618 return status;
619}
620
621
622/****************************************************************************
623 Query disk space.
624****************************************************************************/
625NTSTATUS smbcli_dskattr(struct smbcli_tree *tree, uint32_t *bsize,
626 uint64_t *total, uint64_t *avail)
627{
628 union smb_fsinfo fsinfo_parms;
629 TALLOC_CTX *mem_ctx;
630 NTSTATUS status;
631
632 mem_ctx = talloc_init("smbcli_dskattr");
633
634 fsinfo_parms.dskattr.level = RAW_QFS_SIZE_INFO;
635 status = smb_raw_fsinfo(tree, mem_ctx, &fsinfo_parms);
636 if (NT_STATUS_IS_OK(status)) {
637 *bsize = fsinfo_parms.size_info.out.bytes_per_sector * fsinfo_parms.size_info.out.sectors_per_unit;
638 *total = fsinfo_parms.size_info.out.total_alloc_units;
639 *avail = fsinfo_parms.size_info.out.avail_alloc_units;
640 }
641
642 talloc_free(mem_ctx);
643
644 return status;
645}
646
647
648/****************************************************************************
649 Create and open a temporary file.
650****************************************************************************/
651int smbcli_ctemp(struct smbcli_tree *tree, const char *path, char **tmp_path)
652{
653 union smb_open open_parms;
654 TALLOC_CTX *mem_ctx;
655 NTSTATUS status;
656 int ret = -1;
657
658 mem_ctx = talloc_init("raw_open");
659 if (!mem_ctx) return ret;
660
661 open_parms.openx.level = RAW_OPEN_CTEMP;
662 open_parms.ctemp.in.attrib = 0;
663 open_parms.ctemp.in.directory = path;
664 open_parms.ctemp.in.write_time = 0;
665
666 status = smb_raw_open(tree, mem_ctx, &open_parms);
667 if (NT_STATUS_IS_OK(status)) {
668 if (tmp_path) {
669 *tmp_path = strdup(open_parms.ctemp.out.name);
670 }
671 ret = open_parms.ctemp.out.file.fnum;
672 }
673 talloc_free(mem_ctx);
674 return ret;
675}
Note: See TracBrowser for help on using the repository browser.