Merge commit 'release-4-0-0alpha15' into master4-tmp
[nivanova/samba-autobuild/.git] / source4 / libcli / clifile.c
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
31 static 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 ****************************************************************************/
56 NTSTATUS 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 ****************************************************************************/
65 NTSTATUS 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 ****************************************************************************/
75 static 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
98 NTSTATUS 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 ****************************************************************************/
109 NTSTATUS 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 ****************************************************************************/
120 NTSTATUS 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 ****************************************************************************/
137 NTSTATUS 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 ****************************************************************************/
154 NTSTATUS 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 ****************************************************************************/
168 NTSTATUS 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 ****************************************************************************/
181 NTSTATUS 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 ****************************************************************************/
201 int 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 ****************************************************************************/
242 int 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 ****************************************************************************/
308 NTSTATUS 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 ****************************************************************************/
324 NTSTATUS 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 ****************************************************************************/
352 NTSTATUS 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 ****************************************************************************/
380 NTSTATUS 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 ****************************************************************************/
405 NTSTATUS 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 ****************************************************************************/
441 NTSTATUS 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 ****************************************************************************/
472 NTSTATUS 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 ****************************************************************************/
513 NTSTATUS 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 ****************************************************************************/
547 NTSTATUS 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 ****************************************************************************/
563 NTSTATUS 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 ****************************************************************************/
584 NTSTATUS 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 ****************************************************************************/
599 NTSTATUS 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 ****************************************************************************/
625 NTSTATUS 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 ****************************************************************************/
651 int 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
657         mem_ctx = talloc_init("raw_open");
658         if (!mem_ctx) return -1;
659
660         open_parms.openx.level = RAW_OPEN_CTEMP;
661         open_parms.ctemp.in.attrib = 0;
662         open_parms.ctemp.in.directory = path;
663         open_parms.ctemp.in.write_time = 0;
664
665         status = smb_raw_open(tree, mem_ctx, &open_parms);
666         if (tmp_path) {
667                 *tmp_path = strdup(open_parms.ctemp.out.name);
668         }
669         talloc_free(mem_ctx);
670         if (NT_STATUS_IS_OK(status)) {
671                 return open_parms.ctemp.out.file.fnum;
672         }
673         return -1;
674 }