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