]> andersk Git - moira.git/blob - update/get_file.c
Initial revision
[moira.git] / update / get_file.c
1 /*
2  *      $Source$
3  *      $Header$
4  */
5
6 #ifndef lint
7 static char *rcsid_get_file_c = "$Header$";
8 #endif  lint
9
10 #include <stdio.h>
11 #include "gdb.h"
12 #include <ctype.h>
13 #include <sys/param.h>
14 #include <sys/file.h>
15 #include "update.h"
16 #include "smsu_int.h"
17 #include "kludge.h"
18
19 extern CONNECTION conn;
20 char buf[BUFSIZ];
21
22 extern int code, errno;
23
24 extern int have_authorization, have_file, done;
25
26 int get_block();
27
28 /*
29  * get_file()
30  *
31  * arguments:
32  *      char *pathname
33  *              file to receive
34  *      int file_size
35  *              number of bytes
36  *      int checksum
37  *              linear checksum of bytes
38  *
39  * syntax:
40  * (initial protocol already done)
41  * <<< (int)code        (can we accept the file?)
42  * >>> (STRING)data
43  * <<< (int)code
44  * >>> (STRING)data
45  * <<< (int)code
46  * ...
47  * >>> (STRING)data     (last data block)
48  * <<< (int)code        (from read, write, checksum verify)
49  *
50  * returns:
51  *      int
52  *              0 for success, 1 for failure
53  *
54  * function:
55  *      perform initial preparations and receive file as
56  * a single string, storing it into <pathname>
57  *
58  */
59
60 int
61 get_file(pathname, file_size, checksum)
62     char *pathname;
63     int file_size;
64     int checksum;
65 {
66     int fd, n_written;
67     int found_checksum;
68     
69     if (!have_authorization) {
70         reject_call(SMSU_NO_AUTH);
71         return(1);
72     }
73     if (done)                   /* re-initialize data */
74         initialize();
75     /* unlink old file */
76     (void) unlink(pathname);
77     /* open file descriptor */
78     fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, 0700);
79     if (fd == -1) {
80         code = errno;
81         sprintf(buf, "%s: creating file %s (get_file)",
82                 error_message(code), pathname);
83         sms_log_error(buf);
84         report_error("reporting file creation error (get_file)");
85         return(1);
86     }
87     /* check to see if we've got the disk space */
88     n_written = 0;
89     while (n_written < file_size) {
90         register int n_wrote;
91         n_wrote = write(fd, buf, sizeof(buf));
92         if (n_wrote == -1) {
93             code = errno;
94             sprintf(buf, "%s: verifying free disk space for %s (get_file)",
95                     error_message(code), pathname);
96             sms_log_error(buf);
97             /* do all we can to free the space */
98             (void) unlink(pathname);
99             (void) ftruncate(fd, 0);
100             (void) close(fd);
101             report_error("reporting test-write error (get_file)");
102             return(1);
103         }
104         n_written += n_wrote;
105     }
106     lseek(fd, 0, L_SET);
107     if (send_ok())
108         lose("sending okay for file transfer (get_file)");
109     n_written = 0;
110     while (n_written < file_size && code == 0) {
111         int n_got = get_block(fd, file_size - n_written);
112         if (n_got == -1) {
113             /* get_block has already printed a message */
114             unlink(pathname);
115             return(1);
116         }
117         n_written += n_got;
118         if (n_written != file_size)
119             if (send_ok())
120                 lose("receiving data");
121     }
122     if (code) {
123         code = connection_errno(conn);
124         report_error("reading file (get_file)");
125         return(1);
126     }
127     fsync(fd);
128     ftruncate(fd, file_size);
129     fsync(fd);
130     close(fd);
131     /* validate checksum */
132     fd = open(pathname, O_RDONLY, 0);
133     if (fd == -1) {
134         code = errno;
135         report_error("re-opening file for checksum verification");
136         return(1);
137     }
138     found_checksum = checksum_fd(fd);
139     if (checksum != found_checksum) {
140         code = SMSU_CHECKSUM;
141         com_err(whoami, code, ": expected = %d, found = %d",
142                 checksum, found_checksum);
143         report_error("checksum error");
144         return(1);
145     }
146     close(fd);
147     /* send ack or nack */
148     have_file = 1;
149     if (send_ok()) {
150         code = connection_errno(conn);
151         (void) unlink(pathname);
152         lose("sending ok after file transfer (get_file)");
153         return(1);
154     }
155     return(0);
156 }
157
158 static int
159 get_block(fd, max_size)
160     int fd;
161     int max_size;
162 {
163     STRING data;
164     int n_read, n;
165
166     code = receive_object(conn, (char *)&data, STRING_T);
167     if (code) {
168         code = connection_errno(conn);
169         lose("receiving data file (get_file)");
170     }
171     n_read = MIN(MAX_STRING_SIZE(data), max_size);
172     n = 0;
173     while (n < n_read) {
174         register int n_wrote;
175         n_wrote = write(fd, STRING_DATA(data)+n,
176                         n_read-n);
177         if (n_wrote == -1) {
178             code = errno;
179             sprintf(buf, "%s: writing file (get_file)", error_message(code));
180             sms_log_error(buf);
181             string_free(&data);
182             report_error("reporting write error (get_file)");
183             close(fd);
184             return(-1);
185         }
186         n += n_wrote;
187     }
188     string_free(&data);
189     return(n);
190 }
This page took 0.080987 seconds and 5 git commands to generate.