]> andersk Git - moira.git/blob - update/send_file.c
Handle fencepost of empty file correctly
[moira.git] / update / send_file.c
1 /*
2  *      $Source$
3  *      $Header$
4  */
5
6 #ifndef lint
7 static char *rcsid_send_file_c = "$Header$";
8 #endif  lint
9
10 #include <stdio.h>
11 #include <com_err.h>
12 #include <gdb.h>
13 #include <dcm.h>
14 #include <sms.h>
15 #include <sys/file.h>
16 #include <sys/stat.h>
17 #include <update.h>
18
19
20 extern CONNECTION conn;
21 extern int errno;
22 char buf[BUFSIZ];
23
24 /*
25  * syntax:
26  * (already sent) pathname file_size checksum
27  * <<< (int)code                        can we send it?
28  * >>> data
29  * <<< 0
30  * >>> data
31  * <<< 0
32  * ....
33  * >>> data                             (last block)
34  * <<< 0        (on final write, close, sync, checksum)
35  *
36  * returns:
37  *  0 on success
38  *  1 on error (file not found, etc)
39  */
40
41 int
42 send_file(pathname, target_path)
43 char *pathname;
44 char *target_path;
45 {
46     int n, fd, code, n_to_send;
47     STRING data;
48     struct stat statb;
49
50     string_alloc(&data, UPDATE_BUFSIZ);
51
52     /* send file over */
53     fd = open(pathname, O_RDONLY, 0);
54     if (fd < 0) {
55         com_err(whoami, errno, "unable to open %s for read", pathname);
56         return(SMS_OCONFIG);
57     }
58     if (fstat(fd, &statb)) {
59         com_err(whoami, errno, "unable to stat %s", pathname);
60         close(fd);
61         return(SMS_OCONFIG);
62     }
63     n_to_send = statb.st_size;
64     
65     sprintf(STRING_DATA(data), "XFER_002 %d %d %s",
66             n_to_send, checksum_file(pathname), target_path);
67     code = send_object(conn, (char *)&data, STRING_T);
68     if (code) {
69         com_err(whoami, code, " sending XFER_002 request");
70         close(fd);
71         return(code);
72     }
73     code = receive_object(conn, (char *)&n, INTEGER_T);
74     if (code) {
75         com_err(whoami, code, " getting reply from XFER_002 request");
76         close(fd);
77         return(code);
78     }
79     if (n) {
80         com_err(whoami, n, " transfer request (XFER_002) rejected");
81         close(fd);
82         return(n);
83     }
84     
85     code = receive_object(conn, (char *)&n, INTEGER_T);
86     if (code) {
87         com_err(whoami, connection_errno(conn), ": lost connection");
88         close(fd);
89         return(code);
90     }
91     if (n) {
92         com_err(whoami, n, " from remote server: can't update %s",
93                 pathname);
94         close(fd);
95         return(n);
96     }
97
98     while (n_to_send > 0) {
99 #ifdef  DEBUG
100         printf("n_to_send = %d\n", n_to_send);
101 #endif  /* DEBUG */
102         n = read(fd, STRING_DATA(data), UPDATE_BUFSIZ);
103         if (n < 0) {
104             com_err(whoami, errno, " reading %s for transmission", pathname);
105             close(fd);
106             return(SMS_ABORTED);
107         }
108         MAX_STRING_SIZE(data) = n;
109         code = send_object(conn, (char *)&data, STRING_T);
110         if (code) {
111             com_err(whoami, connection_errno(conn), " transmitting file %s",
112                     pathname);
113             close(fd);
114             return(code);
115         }
116         n_to_send -= n;
117         code = receive_object(conn, (char *)&n, INTEGER_T);
118         if (code) {
119             com_err(whoami, connection_errno(conn),
120                     " awaiting ACK remote server during transmission of %s",
121                     pathname);
122             close(fd);
123             return(code);
124         }
125         if (n) {
126             com_err(whoami, n, " from remote server during transmission of %s",
127                     pathname);
128             close(fd);
129             return(n);
130         }
131     }
132     if (statb.st_size == 0) {
133         code = receive_object(conn, (char *)&n, INTEGER_T);
134         if (code) {
135             com_err(whoami, connection_errno(conn),
136                     " awaiting ACK remote server after transmission of %s",
137                     pathname);
138             close(fd);
139             return(code);
140         }
141         if (n) {
142             com_err(whoami, n, " from remote server after transmission of %s",
143                     pathname);
144             close(fd);
145             return(n);
146         }
147     }
148     close(fd);
149     return(SMS_SUCCESS);
150 }
This page took 0.048223 seconds and 5 git commands to generate.