]> andersk Git - moira.git/blob - update/get_file.c
define macro MIN if not already devined
[moira.git] / update / get_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_get_file_c = "$Header$";
11 #endif  lint
12
13 #include <mit-copyright.h>
14 #include <stdio.h>
15 #include <gdb.h>
16 #include <ctype.h>
17 #include <sys/param.h>
18 #include <sys/file.h>
19 #include <moira.h>
20 #include "update.h"
21
22 #ifndef MIN
23 #define MIN(a,b)    (((a) < (b))?(a):(b))
24 #endif /* MIN */
25
26 extern CONNECTION conn;
27 char buf[BUFSIZ];
28
29 extern int code, errno;
30
31 extern int have_authorization, have_file, done;
32
33 int get_block();
34
35 /*
36  * get_file()
37  *
38  * arguments:
39  *      char *pathname
40  *              file to receive
41  *      int file_size
42  *              number of bytes
43  *      int checksum
44  *              linear checksum of bytes
45  *
46  * syntax:
47  * (initial protocol already done)
48  * <<< (int)code        (can we accept the file?)
49  * >>> (STRING)data
50  * <<< (int)code
51  * >>> (STRING)data
52  * <<< (int)code
53  * ...
54  * >>> (STRING)data     (last data block)
55  * <<< (int)code        (from read, write, checksum verify)
56  *
57  * returns:
58  *      int
59  *              0 for success, 1 for failure
60  *
61  * function:
62  *      perform initial preparations and receive file as
63  * a single string, storing it into <pathname>
64  *
65  */
66
67 int
68 get_file(pathname, file_size, checksum)
69     char *pathname;
70     int file_size;
71     int checksum;
72 {
73     int fd, n_written;
74     int found_checksum;
75     
76     if (!have_authorization) {
77         reject_call(MR_PERM);
78         return(1);
79     }
80     if (done)                   /* re-initialize data */
81         initialize();
82     /* unlink old file */
83     (void) unlink(pathname);
84     /* open file descriptor */
85     fd = open(pathname, O_CREAT|O_EXCL|O_WRONLY, 0700);
86     if (fd == -1) {
87         code = errno;
88         sprintf(buf, "%s: creating file %s (get_file)",
89                 error_message(code), pathname);
90         mr_log_error(buf);
91         report_error("reporting file creation error (get_file)");
92         return(1);
93     }
94     /* check to see if we've got the disk space */
95     n_written = 0;
96     while (n_written < file_size) {
97         register int n_wrote;
98         n_wrote = write(fd, buf, sizeof(buf));
99         if (n_wrote == -1) {
100             code = errno;
101             sprintf(buf, "%s: verifying free disk space for %s (get_file)",
102                     error_message(code), pathname);
103             mr_log_error(buf);
104             /* do all we can to free the space */
105             (void) unlink(pathname);
106             (void) ftruncate(fd, 0);
107             (void) close(fd);
108             report_error("reporting test-write error (get_file)");
109             return(1);
110         }
111         n_written += n_wrote;
112     }
113     lseek(fd, 0, L_SET);
114     if (send_ok())
115         lose("sending okay for file transfer (get_file)");
116     n_written = 0;
117     while (n_written < file_size && code == 0) {
118         int n_got = get_block(fd, file_size - n_written);
119         if (n_got == -1) {
120             /* get_block has already printed a message */
121             unlink(pathname);
122             return(1);
123         }
124         n_written += n_got;
125         if (n_written != file_size)
126             if (send_ok())
127                 lose("receiving data");
128     }
129     if (code) {
130         code = connection_errno(conn);
131         report_error("reading file (get_file)");
132         return(1);
133     }
134     fsync(fd);
135     ftruncate(fd, file_size);
136     fsync(fd);
137     close(fd);
138     /* validate checksum */
139     found_checksum = checksum_file(pathname);
140     if (checksum != found_checksum) {
141         code = MR_MISSINGFILE;
142         com_err(whoami, code, ": expected = %d, found = %d",
143                 checksum, found_checksum);
144         report_error("checksum error");
145         return(1);
146     }
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             mr_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.103037 seconds and 5 git commands to generate.