Import Upstream version 1.8.5
[hcoop/debian/openafs.git] / src / tools / dumpscan / xf_rxcall.c
1 /*
2 * CMUCS AFStools
3 * dumpscan - routines for scanning and manipulating AFS volume dumps
4 *
5 * Copyright (c) 1998 Carnegie Mellon University
6 * All Rights Reserved.
7 *
8 * Permission to use, copy, modify and distribute this software and its
9 * documentation is hereby granted, provided that both the copyright
10 * notice and this permission notice appear in all copies of the
11 * software, derivative works or modified versions, and any portions
12 * thereof, and that both notices appear in supporting documentation.
13 *
14 * CARNEGIE MELLON ALLOWS FREE USE OF THIS SOFTWARE IN ITS "AS IS"
15 * CONDITION. CARNEGIE MELLON DISCLAIMS ANY LIABILITY OF ANY KIND FOR
16 * ANY DAMAGES WHATSOEVER RESULTING FROM THE USE OF THIS SOFTWARE.
17 *
18 * Carnegie Mellon requests users of this software to return to
19 *
20 * Software Distribution Coordinator or Software_Distribution@CS.CMU.EDU
21 * School of Computer Science
22 * Carnegie Mellon University
23 * Pittsburgh PA 15213-3890
24 *
25 * any improvements or extensions that they make and grant Carnegie Mellon
26 * the rights to redistribute these changes.
27 */
28
29 /* xf_rxcall.c - XFILE routines for Rx bulk data transfers */
30
31 #include <sys/types.h>
32 #include <netinet/in.h>
33 #include <errno.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <fcntl.h>
37 #include <netdb.h>
38
39 #include "xfiles.h"
40 #include "xf_errs.h"
41
42 #include <rx/xdr.h>
43 #include <rx/rx.h>
44 #include <rx/rx_null.h>
45 #include <rx/rxkad.h>
46 #include <afs/auth.h>
47 #include <afs/cellconfig.h>
48 #include <afs/vlserver.h>
49 #include <afs/afsint.h>
50 #include <afs/volser.h>
51 #include <afs/volint.h>
52
53 #ifndef AFSCONF_CLIENTNAME
54 #include <afs/dirpath.h>
55 #define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH
56 #endif
57
58 #define O_MODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
59
60 struct rxinfo {
61 struct rx_connection *conn; /* connection */
62 struct rx_call *call; /* call */
63 afs_int32 tid; /* volser transaction ID */
64 afs_uint32 code; /* result code */
65 };
66
67 static afs_uint32
68 xf_rxcall_do_read(XFILE * X, void *buf, afs_uint32 count)
69 {
70 struct rxinfo *i = X->refcon;
71 afs_uint32 xcount;
72
73 xcount = rx_Read(i->call, buf, count);
74 if (xcount == count)
75 return 0;
76 i->code = rx_EndCall(i->call, 0);
77 i->call = 0;
78 return i->code ? i->code : ERROR_XFILE_RDONLY;
79 }
80
81
82 static afs_uint32
83 xf_rxcall_do_write(XFILE * X, void *buf, afs_uint32 count)
84 {
85 struct rxinfo *i = X->refcon;
86 afs_uint32 xcount;
87
88 xcount = rx_Write(i->call, buf, count);
89 if (xcount == count)
90 return 0;
91 i->code = rx_EndCall(i->call, 0);
92 i->call = 0;
93 return i->code;
94 }
95
96
97 static afs_uint32
98 xf_rxcall_do_close(XFILE * X)
99 {
100 struct rxinfo *i = X->refcon;
101 afs_uint32 code;
102
103 if (i->call) {
104 code = rx_EndCall(i->call, i->code);
105 i->call = 0;
106 } else {
107 code = i->code;
108 }
109 free(i);
110 return code;
111 }
112
113
114 static afs_uint32
115 xf_voldump_do_close(XFILE * X)
116 {
117 struct rxinfo *i = X->refcon;
118 struct rx_connection *conn = i->conn;
119 afs_int32 code, rcode, xcode;
120 afs_int32 tid = i->tid;
121
122 code = xf_rxcall_do_close(X);
123 xcode = AFSVolEndTrans(conn, tid, &rcode);
124 if (!code)
125 code = xcode ? xcode : rcode;
126 return code;
127 }
128
129
130 afs_uint32
131 xfopen_rxcall(XFILE * X, int flag, struct rx_call * call)
132 {
133 struct rxinfo *i;
134
135 flag &= O_MODE_MASK;
136 if (flag == O_WRONLY)
137 return ERROR_XFILE_WRONLY;
138 memset(X, 0, sizeof(*X));
139 if (!(i = (struct rxinfo *)malloc(sizeof(struct rxinfo))))
140 return ENOMEM;
141 i->call = call;
142 i->code = 0;
143 X->do_read = xf_rxcall_do_read;
144 X->do_write = xf_rxcall_do_write;
145 X->do_close = xf_rxcall_do_close;
146 X->is_writable = (flag == O_RDWR);
147 X->refcon = i;
148 return 0;
149 }
150
151
152 afs_uint32
153 xfopen_voldump(XFILE * X, struct rx_connection * conn, afs_int32 part,
154 afs_int32 volid, afs_int32 date)
155 {
156 struct rx_call *call;
157 struct rxinfo *i;
158 afs_int32 code, rcode;
159 afs_int32 tid;
160
161 if ((code = AFSVolTransCreate(conn, volid, part, ITBusy, &tid)))
162 return code;
163 call = rx_NewCall(conn);
164 if ((code = StartAFSVolDump(call, tid, date))
165 || (code = xfopen_rxcall(X, O_RDONLY, call))) {
166 rx_EndCall(call, 0);
167 AFSVolEndTrans(conn, tid, &rcode);
168 return code;
169 }
170
171 i = X->refcon;
172 i->conn = conn;
173 i->tid = tid;
174 X->do_close = xf_voldump_do_close;
175 return 0;
176 }
177
178
179 afs_uint32
180 xfon_voldump(XFILE * X, int flag, char *name)
181 {
182 struct hostent *he;
183 struct rx_securityClass *class;
184 struct rx_connection *conn;
185 struct ktc_principal sname;
186 struct ktc_token token;
187 struct afsconf_dir *confdir;
188 afs_uint32 code, server_addr = 0;
189 afs_int32 volid, date, partid = 0;
190 int isnum, index;
191 char *x, *y;
192
193 /* Parse out the optional date and server location */
194 if ((code = rx_Init(0)))
195 return code;
196 if (!(name = strdup(name)))
197 return ENOMEM;
198 if ((x = strrchr(name, ','))) {
199 *x++ = 0;
200 date = atoi(x);
201 } else {
202 date = 0;
203 }
204 if ((x = strrchr(name, '@'))) {
205 int a, b, c, d;
206
207 *x++ = 0;
208 if (!(y = strchr(x, '/'))) {
209 free(name);
210 return VL_BADPARTITION;
211 }
212 *y++ = 0;
213 if (sscanf(x, "%d.%d.%d.%d", &a, &b, &c, &d) == 4 && a >= 0
214 && a <= 255 && b >= 0 && b <= 255 && c >= 0 && c <= 255 && d >= 0
215 && d <= 255) {
216 server_addr = (a << 24) | (b << 16) | (c << 8) | d;
217 server_addr = htonl(server_addr);
218 } else {
219 he = gethostbyname(x);
220 if (!he) {
221 free(name);
222 return VL_BADSERVER;
223 }
224 memcpy(&server_addr, he->h_addr, sizeof(server_addr));
225 }
226 partid = volutil_GetPartitionID(y);
227 if (partid < 0) {
228 free(name);
229 return VL_BADPARTITION;
230 }
231 }
232
233 /* Get tokens and set up a security object */
234 confdir = afsconf_Open(AFSCONF_CLIENTNAME);
235 if (!confdir) {
236 free(name);
237 return AFSCONF_NODB;
238 }
239 if ((code = afsconf_GetLocalCell(confdir, sname.cell, MAXKTCNAMELEN))) {
240 free(name);
241 return code;
242 }
243 afsconf_Close(confdir);
244 strcpy(sname.name, "afs");
245 sname.instance[0] = 0;
246 code = ktc_GetToken(&sname, &token, sizeof(token), 0);
247 if (code) {
248 class = rxnull_NewClientSecurityObject();
249 index = 0;
250 } else {
251 class =
252 rxkad_NewClientSecurityObject(rxkad_clear, &token.sessionKey,
253 token.kvno, token.ticketLen,
254 token.ticket);
255 index = 2;
256 }
257
258 /* Figure out the volume ID, looking it up in the VLDB if neccessary.
259 * Also look up the server and partition, if they were not specified.
260 */
261 for (isnum = 1, y = name; *y; y++)
262 if (*y < '0' || *y > '9')
263 isnum = 0;
264 if (isnum) {
265 volid = atoi(name);
266 if (!x) {
267 fprintf(stderr, "XXX: need to lookup volume by ID!\n");
268 exit(-1);
269 }
270 } else {
271 fprintf(stderr, "XXX: need to lookup volume by name!\n");
272 exit(-1);
273 }
274 free(name);
275
276 /* Establish a connection and start the call */
277 conn =
278 rx_NewConnection(server_addr, htons(AFSCONF_VOLUMEPORT),
279 VOLSERVICE_ID, class, index);
280 return xfopen_voldump(X, conn, partid, volid, date);
281 }