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