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