]> andersk Git - moira.git/blob - update/send_file.c
Do a better job with returning error codes: add ERROR_TABLE_BASE_krb
[moira.git] / update / send_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_send_file_c = "$Header$";
11 #endif
12
13 #include <mit-copyright.h>
14 #include <stdio.h>
15 #include <com_err.h>
16 #include <gdb.h>
17 #include <dcm.h>
18 #include <moira.h>
19 #include <sys/file.h>
20 #include <sys/stat.h>
21 #include <des.h>
22 #include <krb.h>
23 #include <update.h>
24 #ifdef POSIX
25 #include <fcntl.h>
26 #endif
27
28 extern CONNECTION conn;
29 extern int errno;
30 char buf[BUFSIZ];
31 extern C_Block session;
32
33 /*
34  * syntax:
35  * (already sent) pathname file_size checksum
36  * <<< (int)code                        can we send it?
37  * >>> data
38  * <<< 0
39  * >>> data
40  * <<< 0
41  * ....
42  * >>> data                             (last block)
43  * <<< 0        (on final write, close, sync, checksum)
44  *
45  * returns:
46  *  0 on success
47  *  1 on error (file not found, etc)
48  */
49
50 int
51 send_file(pathname, target_path, encrypt)
52 char *pathname;
53 char *target_path;
54 int  encrypt;
55 {
56     int n, fd, code, n_to_send, i;
57     STRING data;
58     unsigned char dst[UPDATE_BUFSIZ + 8], *src;
59     struct stat statb;
60     des_key_schedule sched;
61     des_cblock ivec;
62
63     /* send file over */
64     fd = open(pathname, O_RDONLY, 0);
65     if (fd < 0) {
66         com_err(whoami, errno, "unable to open %s for read", pathname);
67         return(MR_OCONFIG);
68     }
69     if (fstat(fd, &statb)) {
70         com_err(whoami, errno, "unable to stat %s", pathname);
71         close(fd);
72         return(MR_OCONFIG);
73     }
74     n_to_send = statb.st_size;
75     
76     string_alloc(&data, UPDATE_BUFSIZ);
77     sprintf(STRING_DATA(data), "XFER_00%c %d %d %s",
78             (encrypt ? '3' : '2'), n_to_send,
79             checksum_file(pathname), target_path);
80     code = send_object(conn, (char *)&data, STRING_T);
81     if (code) {
82         com_err(whoami, connection_errno(conn), " sending XFER request");
83         close(fd);
84         return(connection_errno(conn));
85     }
86     code = receive_object(conn, (char *)&n, INTEGER_T);
87     if (code) {
88         com_err(whoami, connection_errno(conn),
89                 " getting reply from XFER request");
90         close(fd);
91         return(connection_errno(conn));
92     }
93     if (n) {
94         com_err(whoami, n, " transfer request (XFER) rejected");
95         close(fd);
96         return(n);
97     }
98     
99     code = receive_object(conn, (char *)&n, INTEGER_T);
100     if (code) {
101         com_err(whoami, connection_errno(conn), ": lost connection");
102         close(fd);
103         return(connection_errno(conn));
104     }
105     if (n) {
106         com_err(whoami, n, " from remote server: can't update %s",
107                 pathname);
108         close(fd);
109         return(n);
110     }
111
112     if (encrypt) {
113 #ifdef DEBUG
114         printf("Session key %02x %02x %02x %02x  %02x %02x %02x %02x\n",
115                session[0], session[1], session[2], session[3], 
116                session[4], session[5], session[6], session[7]);
117 #endif /* DEBUG */
118         des_key_sched(session, sched);
119 #ifdef POSIX
120         memmove(ivec, session, sizeof(ivec));
121 #else
122         bcopy(session, ivec, sizeof(ivec));
123 #endif
124     }
125
126     while (n_to_send > 0) {
127 #ifdef  DEBUG
128         printf("n_to_send = %d\n", n_to_send);
129 #endif  /* DEBUG */
130         n = read(fd, STRING_DATA(data), UPDATE_BUFSIZ);
131         if (n < 0) {
132             com_err(whoami, errno, " reading %s for transmission", pathname);
133             close(fd);
134             return(MR_ABORTED);
135         }
136         MAX_STRING_SIZE(data) = n;
137         if (encrypt) {
138             src = (unsigned char *)STRING_DATA(data);
139 #ifdef POSIX
140             memmove(dst, src, n);
141 #else
142             bcopy(src, dst, n);
143 #endif
144             memset(dst + n, 0, 7);
145             /* encrypt! */
146             des_pcbc_encrypt(dst, src, n, sched, ivec, 0);
147             /* save vector to continue chaining */
148             for (i = 0; i < 8; i++)
149               ivec[i] = dst[n - 8 + i] ^ src[n - 8 + i];
150             /* round up to multiple of 8 */
151             data.length = (data.length + 7) & 0xfffffff8;
152         }
153         code = send_object(conn, (char *)&data, STRING_T);
154         if (code) {
155             com_err(whoami, connection_errno(conn), " transmitting file %s",
156                     pathname);
157             close(fd);
158             return(connection_errno(conn));
159         }
160         n_to_send -= n;
161         code = receive_object(conn, (char *)&n, INTEGER_T);
162         if (code) {
163             com_err(whoami, connection_errno(conn),
164                     " awaiting ACK remote server during transmission of %s",
165                     pathname);
166             close(fd);
167             return(connection_errno(conn));
168         }
169         if (n) {
170             com_err(whoami, n, " from remote server during transmission of %s",
171                     pathname);
172             close(fd);
173             return(n);
174         }
175     }
176     if (statb.st_size == 0) {
177         code = receive_object(conn, (char *)&n, INTEGER_T);
178         if (code) {
179             com_err(whoami, connection_errno(conn),
180                     " awaiting ACK remote server after transmission of %s",
181                     pathname);
182             close(fd);
183             return(connection_errno(conn));
184         }
185         if (n) {
186             com_err(whoami, n, " from remote server after transmission of %s",
187                     pathname);
188             close(fd);
189             return(n);
190         }
191     }
192     close(fd);
193     return(MR_SUCCESS);
194 }
This page took 0.048598 seconds and 5 git commands to generate.