source: branches/samba-3.5.x/source4/libcli/clifile.c@ 737

Last change on this file since 737 was 414, checked in by Herwig Bauernfeind, 15 years ago

Samba 3.5.0: Initial import

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