]> andersk Git - moira.git/blame_incremental - update/get_file.c
Add MR_CONTAINER_NO_PARENT error code.
[moira.git] / update / get_file.c
... / ...
CommitLineData
1/* $Id$
2 *
3 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
4 * For copying and distribution information, please see the file
5 * <mit-copyright.h>.
6 */
7
8#include <mit-copyright.h>
9#include <moira.h>
10#include "update_server.h"
11#include "update.h"
12
13#include <errno.h>
14#include <fcntl.h>
15#include <stdio.h>
16#include <stdlib.h>
17#include <string.h>
18#include <unistd.h>
19
20#include <des.h>
21
22RCSID("$Header$");
23
24#ifndef MIN
25#define MIN(a, b) (((a) < (b)) ? (a) : (b))
26#endif /* MIN */
27
28static des_key_schedule sched;
29static des_cblock ivec;
30extern des_cblock session;
31
32static int get_block(int conn, int fd, int max_size, int encrypt);
33
34/*
35 * get_file()
36 *
37 * arguments:
38 * char *pathname
39 * file to receive
40 * int file_size
41 * number of bytes
42 * int checksum
43 * linear checksum of bytes
44 *
45 * syntax:
46 * (initial protocol already done)
47 * <<< (int)code (can we accept the file?)
48 * >>> (STRING)data
49 * <<< (int)code
50 * >>> (STRING)data
51 * <<< (int)code
52 * ...
53 * >>> (STRING)data (last data block)
54 * <<< (int)code (from read, write, checksum verify)
55 *
56 * returns:
57 * int
58 * 0 for success, 1 for failure
59 *
60 * function:
61 * perform initial preparations and receive file as
62 * a single string, storing it into <pathname>
63 *
64 */
65
66int get_file(int conn, char *pathname, int file_size, int checksum,
67 int mode, int encrypt)
68{
69 int fd, n_written, code;
70 int found_checksum;
71 char buf[BUFSIZ];
72
73 if (!have_authorization)
74 {
75 send_int(conn, MR_PERM);
76 return 1;
77 }
78 if (setuid(uid) < 0)
79 {
80 com_err(whoami, errno, "Unable to setuid to %d\n", uid);
81 exit(1);
82 }
83
84 /* unlink old file */
85 if (!config_lookup("noclobber"))
86 unlink(pathname);
87 /* open file descriptor */
88 fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, mode);
89 if (fd == -1)
90 {
91 code = errno;
92 com_err(whoami, errno, "creating file %s (get_file)", pathname);
93 send_int(conn, code);
94 if (setuid(0) < 0)
95 {
96 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
97 exit(1);
98 }
99 return 1;
100 }
101
102 /* check to see if we've got the disk space */
103 n_written = 0;
104 while (n_written < file_size)
105 {
106 int n_wrote;
107 n_wrote = write(fd, buf, sizeof(buf));
108 if (n_wrote == -1)
109 {
110 code = errno;
111 com_err(whoami, code, "verifying free disk space for %s (get_file)",
112 pathname);
113 send_int(conn, code);
114
115 /* do all we can to free the space */
116 unlink(pathname);
117 ftruncate(fd, 0);
118 close(fd);
119
120 if (setuid(0) < 0)
121 {
122 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
123 exit(1);
124 }
125 return 1;
126 }
127 n_written += n_wrote;
128 }
129
130 lseek(fd, 0, SEEK_SET);
131 send_ok(conn);
132
133 if (encrypt)
134 {
135 des_key_sched(session, sched);
136 memcpy(ivec, session, sizeof(ivec));
137 }
138
139 n_written = 0;
140 while (n_written < file_size)
141 {
142 int n_got = get_block(conn, fd, file_size - n_written, encrypt);
143
144 if (n_got == -1)
145 {
146 /* get_block has already printed a message */
147 unlink(pathname);
148 if (setuid(0) < 0)
149 {
150 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
151 exit(1);
152 }
153 return 1;
154 }
155 n_written += n_got;
156 if (n_written != file_size)
157 send_ok(conn);
158 }
159
160 fsync(fd);
161 ftruncate(fd, file_size);
162 fsync(fd);
163 close(fd);
164
165 if (setuid(0) < 0)
166 {
167 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
168 exit(1);
169 }
170
171 /* validate checksum */
172 found_checksum = checksum_file(pathname);
173 if (checksum != found_checksum)
174 {
175 code = MR_MISSINGFILE;
176 com_err(whoami, code, ": expected = %d, found = %d",
177 checksum, found_checksum);
178 send_int(conn, code);
179 return 1;
180 }
181
182 send_ok(conn);
183 return 0;
184}
185
186static int get_block(int conn, int fd, int max_size, int encrypt)
187{
188 char *data;
189 size_t len;
190 int n_read, n, i, code;
191
192 recv_string(conn, &data, &len);
193
194 if (encrypt)
195 {
196 char *unenc = malloc(len);
197
198 if (!unenc)
199 {
200 send_int(conn, ENOMEM);
201 return -1;
202 }
203
204 des_pcbc_encrypt(data, unenc, len, sched, ivec, 1);
205 for (i = 0; i < 8; i++)
206 ivec[i] = data[len - 8 + i] ^ unenc[len - 8 + i];
207 free(data);
208 data = unenc;
209 }
210
211 n_read = MIN(len, max_size);
212 n = 0;
213 while (n < n_read)
214 {
215 int n_wrote;
216 n_wrote = write(fd, data + n, n_read - n);
217 if (n_wrote == -1)
218 {
219 code = errno;
220 com_err(whoami, errno, "writing file (get_file)");
221 send_int(conn, code);
222 free(data);
223 close(fd);
224 return -1;
225 }
226 n += n_wrote;
227 }
228 free(data);
229 return n;
230}
This page took 0.642417 seconds and 5 git commands to generate.