source: trunk/third/moira/update/send_file.c @ 23178

Revision 23178, 3.7 KB checked in by broder, 16 years ago (diff)
Take a new snapshot from CVS for Moira, and add a debathena-moira-update-server package
Line 
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
23RCSID("$Header$");
24
25extern 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
44int 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}
Note: See TracBrowser for help on using the repository browser.