]> andersk Git - moira.git/blame - update/get_file.c
fix RCS Id strings
[moira.git] / update / get_file.c
CommitLineData
7ac48069 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>.
de56407f 6 */
de56407f 7
546bc43b 8#include <mit-copyright.h>
2ad0a777 9#include <moira.h>
7ac48069 10#include "update_server.h"
de56407f 11#include "update.h"
de56407f 12
7ac48069 13#include <errno.h>
14#include <fcntl.h>
15#include <stdio.h>
16#include <unistd.h>
17
18#include <des.h>
19#include <gdb.h>
20
21RCSID("$Header$");
22
7b18e95b 23#ifndef MIN
5eaef520 24#define MIN(a, b) (((a) < (b)) ? (a) : (b))
7b18e95b 25#endif /* MIN */
26
de56407f 27extern CONNECTION conn;
7da203a3 28extern char buf[BUFSIZ];
de56407f 29
7ac48069 30extern int code, uid;
7da203a3 31extern char *whoami;
de56407f 32
33extern int have_authorization, have_file, done;
32df7737 34extern C_Block session;
d599d457 35static des_key_schedule sched;
36static des_cblock ivec;
de56407f 37
7ac48069 38static int get_block(int fd, int max_size, int encrypt);
de56407f 39
40/*
41 * get_file()
42 *
43 * arguments:
44 * char *pathname
45 * file to receive
46 * int file_size
47 * number of bytes
48 * int checksum
49 * linear checksum of bytes
50 *
51 * syntax:
52 * (initial protocol already done)
53 * <<< (int)code (can we accept the file?)
54 * >>> (STRING)data
55 * <<< (int)code
56 * >>> (STRING)data
57 * <<< (int)code
58 * ...
59 * >>> (STRING)data (last data block)
60 * <<< (int)code (from read, write, checksum verify)
61 *
62 * returns:
63 * int
64 * 0 for success, 1 for failure
65 *
66 * function:
67 * perform initial preparations and receive file as
68 * a single string, storing it into <pathname>
69 *
70 */
71
5eaef520 72int get_file(char *pathname, int file_size, int checksum,
73 int mode, int encrypt)
de56407f 74{
5eaef520 75 int fd, n_written;
76 int found_checksum;
77
78 if (!have_authorization)
79 {
80 reject_call(MR_PERM);
81 return 1;
de56407f 82 }
5eaef520 83 if (done) /* re-initialize data */
84 initialize();
85 if (setuid(uid) < 0)
86 {
87 com_err(whoami, errno, "Unable to setuid to %d\n", uid);
88 exit(1);
35fd45e2 89 }
5eaef520 90 /* unlink old file */
91 if (!config_lookup("noclobber"))
92 unlink(pathname);
93 /* open file descriptor */
94 fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, mode);
95 if (fd == -1)
96 {
97 code = errno;
98 sprintf(buf, "%s: creating file %s (get_file)",
99 error_message(code), pathname);
100 mr_log_error(buf);
101 report_error("reporting file creation error (get_file)");
102 if (setuid(0) < 0)
103 {
104 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
105 exit(1);
35fd45e2 106 }
5eaef520 107 return 1;
de56407f 108 }
5eaef520 109 /* check to see if we've got the disk space */
110 n_written = 0;
111 while (n_written < file_size)
112 {
44d12d58 113 int n_wrote;
5eaef520 114 n_wrote = write(fd, buf, sizeof(buf));
115 if (n_wrote == -1)
116 {
117 code = errno;
118 sprintf(buf, "%s: verifying free disk space for %s (get_file)",
119 error_message(code), pathname);
120 mr_log_error(buf);
121 /* do all we can to free the space */
122 unlink(pathname);
123 ftruncate(fd, 0);
124 close(fd);
125 report_error("reporting test-write error (get_file)");
126 if (setuid(0) < 0)
127 {
128 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
129 exit(1);
35fd45e2 130 }
5eaef520 131 return 1;
de56407f 132 }
5eaef520 133 n_written += n_wrote;
de56407f 134 }
7ac48069 135 lseek(fd, 0, SEEK_SET);
5eaef520 136 if (send_ok())
137 lose("sending okay for file transfer (get_file)");
138 if (encrypt)
139 {
140 des_key_sched(session, sched);
141 memcpy(ivec, session, sizeof(ivec));
d599d457 142 }
5eaef520 143 n_written = 0;
144 while (n_written < file_size && code == 0)
145 {
146 int n_got = get_block(fd, file_size - n_written, encrypt);
147 if (n_got == -1)
148 {
149 /* get_block has already printed a message */
150 unlink(pathname);
151 if (setuid(0) < 0)
152 {
153 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
154 exit(1);
35fd45e2 155 }
5eaef520 156 return 1;
157 }
158 n_written += n_got;
159 if (n_written != file_size)
160 {
161 if (send_ok())
162 lose("receiving data");
de56407f 163 }
de56407f 164 }
5eaef520 165 if (code)
166 {
167 code = connection_errno(conn);
168 report_error("reading file (get_file)");
169 if (setuid(0) < 0)
170 {
171 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
172 exit(1);
35fd45e2 173 }
5eaef520 174 return 1;
de56407f 175 }
5eaef520 176 fsync(fd);
177 ftruncate(fd, file_size);
178 fsync(fd);
179 close(fd);
180 if (setuid(0) < 0)
181 {
182 com_err(whoami, errno, "Unable to setuid back to %d\n", 0);
183 exit(1);
35fd45e2 184 }
5eaef520 185 /* validate checksum */
186 found_checksum = checksum_file(pathname);
187 if (checksum != found_checksum)
188 {
189 code = MR_MISSINGFILE;
190 com_err(whoami, code, ": expected = %d, found = %d",
191 checksum, found_checksum);
192 report_error("checksum error");
193 return 1;
de56407f 194 }
5eaef520 195 /* send ack or nack */
196 have_file = 1;
197 if (send_ok())
198 {
199 code = connection_errno(conn);
200 unlink(pathname);
201 lose("sending ok after file transfer (get_file)");
202 return 1;
de56407f 203 }
5eaef520 204 return 0;
de56407f 205}
206
5eaef520 207static int get_block(int fd, int max_size, int encrypt)
de56407f 208{
5eaef520 209 STRING data;
210 unsigned char dst[UPDATE_BUFSIZ + 8], *src;
211 int n_read, n, i;
de56407f 212
5eaef520 213 code = receive_object(conn, (char *)&data, STRING_T);
214 if (code)
215 {
216 code = connection_errno(conn);
217 lose("receiving data file (get_file)");
de56407f 218 }
32df7737 219
5eaef520 220 if (encrypt)
221 {
222 src = (unsigned char *)STRING_DATA(data);
223 n = MAX_STRING_SIZE(data);
224 des_pcbc_encrypt(src, dst, n, sched, ivec, 1);
225 for (i = 0; i < 8; i++)
226 ivec[i] = src[n - 8 + i] ^ dst[n - 8 + i];
227 memcpy(STRING_DATA(data), dst, n);
32df7737 228 }
229
5eaef520 230 n_read = MIN(MAX_STRING_SIZE(data), max_size);
231 n = 0;
232 while (n < n_read)
233 {
44d12d58 234 int n_wrote;
5eaef520 235 n_wrote = write(fd, STRING_DATA(data) + n, n_read - n);
236 if (n_wrote == -1)
237 {
238 code = errno;
239 sprintf(buf, "%s: writing file (get_file)", error_message(code));
240 mr_log_error(buf);
241 string_free(&data);
242 report_error("reporting write error (get_file)");
243 close(fd);
244 return -1;
de56407f 245 }
5eaef520 246 n += n_wrote;
de56407f 247 }
5eaef520 248 string_free(&data);
249 return n;
de56407f 250}
This page took 0.117139 seconds and 5 git commands to generate.