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