Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * Utility functions to transfer files.
4 : *
5 : * Copyright (C) Jeremy Allison 2001-2002
6 : * Copyright (C) Michael Adam 2008
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 :
23 : #include <includes.h>
24 : #include "transfer_file.h"
25 : #include "lib/util/sys_rw.h"
26 :
27 : /****************************************************************************
28 : Transfer some data between two fd's.
29 : ****************************************************************************/
30 :
31 : #ifndef TRANSFER_BUF_SIZE
32 : #define TRANSFER_BUF_SIZE 65536
33 : #endif
34 :
35 :
36 26 : ssize_t transfer_file_internal(void *in_file,
37 : void *out_file,
38 : size_t n,
39 : ssize_t (*pread_fn)(void *, void *, size_t, off_t),
40 : ssize_t (*pwrite_fn)(void *, const void *, size_t, off_t))
41 : {
42 2 : char *buf;
43 26 : size_t total = 0;
44 2 : ssize_t read_ret;
45 2 : ssize_t write_ret;
46 2 : size_t num_to_read_thistime;
47 26 : size_t num_written = 0;
48 26 : off_t offset = 0;
49 :
50 26 : if (n == 0) {
51 0 : return 0;
52 : }
53 :
54 26 : if ((buf = SMB_MALLOC_ARRAY(char, TRANSFER_BUF_SIZE)) == NULL) {
55 0 : return -1;
56 : }
57 :
58 2 : do {
59 26 : num_to_read_thistime = MIN((n - total), TRANSFER_BUF_SIZE);
60 :
61 26 : read_ret = (*pread_fn)(in_file, buf, num_to_read_thistime, offset);
62 26 : if (read_ret == -1) {
63 0 : DEBUG(0,("transfer_file_internal: read failure. "
64 : "Error = %s\n", strerror(errno) ));
65 0 : SAFE_FREE(buf);
66 0 : return -1;
67 : }
68 26 : if (read_ret == 0) {
69 0 : break;
70 : }
71 :
72 24 : num_written = 0;
73 :
74 52 : while (num_written < read_ret) {
75 28 : write_ret = (*pwrite_fn)(out_file, buf + num_written,
76 : read_ret - num_written,
77 26 : offset + num_written);
78 :
79 26 : if (write_ret == -1) {
80 0 : DEBUG(0,("transfer_file_internal: "
81 : "write failure. Error = %s\n",
82 : strerror(errno) ));
83 0 : SAFE_FREE(buf);
84 0 : return -1;
85 : }
86 26 : if (write_ret == 0) {
87 0 : return (ssize_t)total;
88 : }
89 :
90 26 : num_written += (size_t)write_ret;
91 : }
92 :
93 26 : total += (size_t)read_ret;
94 26 : offset += (off_t)read_ret;
95 26 : } while (total < n);
96 :
97 26 : SAFE_FREE(buf);
98 26 : return (ssize_t)total;
99 : }
100 :
101 0 : static ssize_t sys_pread_fn(void *file, void *buf, size_t len, off_t offset)
102 : {
103 0 : int *fd = (int *)file;
104 :
105 0 : return sys_pread(*fd, buf, len, offset);
106 : }
107 :
108 0 : static ssize_t sys_pwrite_fn(void *file, const void *buf, size_t len, off_t offset)
109 : {
110 0 : int *fd = (int *)file;
111 :
112 0 : return sys_pwrite(*fd, buf, len, offset);
113 : }
114 :
115 0 : off_t transfer_file(int infd, int outfd, off_t n)
116 : {
117 0 : return (off_t)transfer_file_internal(&infd, &outfd, (size_t)n,
118 : sys_pread_fn, sys_pwrite_fn);
119 : }
|