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