test-suite-pull-tools-directly-in-20020114
[openafs.git] / src / tests / 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/volser.h>
50
51 #ifndef AFSCONF_CLIENTNAME
52 #include <afs/dirpath.h>
53 #define AFSCONF_CLIENTNAME AFSDIR_CLIENT_ETC_DIRPATH
54 #endif
55
56 #define O_MODE_MASK (O_RDONLY | O_WRONLY | O_RDWR)
57
58 struct rxinfo {
59   struct rx_connection *conn;  /* connection */
60   struct rx_call *call;        /* call */
61   afs_int32 tid;                   /* volser transaction ID */
62   afs_uint32 code;                /* result code */
63 };
64
65 static afs_uint32 xf_rxcall_do_read(XFILE *X, void *buf, afs_uint32 count)
66 {
67   struct rxinfo *i = X->refcon;
68   afs_uint32 xcount;
69
70   xcount = rx_Read(i->call, buf, count);
71   if (xcount == count) return 0;
72   i->code = rx_EndCall(i->call, 0);
73   i->call = 0;
74   return i->code ? i->code : ERROR_XFILE_RDONLY;
75 }
76
77
78 static afs_uint32 xf_rxcall_do_write(XFILE *X, void *buf, afs_uint32 count)
79 {
80   struct rxinfo *i = X->refcon;
81   afs_uint32 xcount;
82
83   xcount = rx_Write(i->call, buf, count);
84   if (xcount == count) return 0;
85   i->code = rx_EndCall(i->call, 0);
86   i->call = 0;
87   return i->code;
88 }
89
90
91 static afs_uint32 xf_rxcall_do_close(XFILE *X)
92 {
93   struct rxinfo *i = X->refcon;
94   afs_uint32 code;
95
96   if (i->call) {
97     code = rx_EndCall(i->call, i->code);
98     i->call = 0;
99   } else {
100     code = i->code;
101   }
102   free(i);
103   return code;
104 }
105
106
107 static afs_uint32 xf_voldump_do_close(XFILE *X)
108 {
109   struct rxinfo *i = X->refcon;
110   struct rx_connection *conn = i->conn;
111   afs_uint32 code, rcode, xcode;
112   afs_int32 tid = i->tid;
113
114   code = xf_rxcall_do_close(X);
115   xcode = AFSVolEndTrans(conn, tid, &rcode);
116   if (!code) code = xcode ? xcode : rcode;
117   return code;
118 }
119
120
121 afs_uint32 xfopen_rxcall(XFILE *X, int flag, struct rx_call *call)
122 {
123   struct rxinfo *i;
124
125   flag &= O_MODE_MASK;
126   if (flag == O_WRONLY) return ERROR_XFILE_WRONLY;
127   memset(X, 0, sizeof(*X));
128   if (!(i = (struct rxinfo *)malloc(sizeof(struct rxinfo)))) return ENOMEM;
129   i->call = call;
130   i->code = 0;
131   X->do_read  = xf_rxcall_do_read;
132   X->do_write = xf_rxcall_do_write;
133   X->do_close = xf_rxcall_do_close;
134   X->is_writable = (flag == O_RDWR);
135   X->refcon = i;
136   return 0;
137 }
138
139
140 afs_uint32 xfopen_voldump(XFILE *X, struct rx_connection *conn,
141                        afs_int32 part, afs_int32 volid, afs_int32 date)
142 {
143   struct rx_call *call;
144   struct rxinfo *i;
145   afs_uint32 code, rcode;
146   afs_int32 tid;
147
148   if (code = AFSVolTransCreate(conn, volid, part, ITBusy, &tid)) return code;
149   call = rx_NewCall(conn);
150   if ((code = StartAFSVolDump(call, tid, date))
151   ||  (code = xfopen_rxcall(X, O_RDONLY, call))) {
152     rx_EndCall(call, 0);
153     AFSVolEndTrans(conn, tid, &rcode);
154     return code;
155   }
156
157   i = X->refcon;
158   i->conn = conn;
159   i->tid = tid;
160   X->do_close = xf_voldump_do_close;
161   return 0;
162 }
163
164
165 afs_uint32 xfon_voldump(XFILE *X, int flag, char *name)
166 {
167   struct hostent *he;
168   struct rx_securityClass *class;
169   struct rx_connection *conn;
170   struct ktc_principal sname;
171   struct ktc_token token;
172   struct afsconf_dir *confdir;
173   afs_uint32 code, server_addr;
174   afs_int32 volid, partid, date;
175   int isnum, index;
176   char *x, *y;
177
178   /* Parse out the optional date and server location */
179   if (code = rx_Init(0)) return code;
180   if (!(name = strdup(name))) return ENOMEM;
181   if (x = strrchr(name, ',')) {
182     *x++ = 0;
183     date = atoi(x);
184   } else {
185     date = 0;
186   }
187   if (x = strrchr(name, '@')) {
188     int a, b, c, d;
189
190     *x++ = 0;
191     if (!(y = strchr(x, '/'))) {
192       free(name);
193       return VL_BADPARTITION;
194     }
195     *y++ = 0;
196     if (sscanf(x, "%d.%d.%d.%d", &a, &b, &c, &d) == 4
197     &&  a >= 0 && a <= 255 && b >= 0 && b <= 255
198     &&  c >= 0 && c <= 255 && d >= 0 && d <= 255) {
199       server_addr = (a << 24) | (b << 16) | (c << 8) | d;
200       server_addr = htonl(server_addr);
201     } else {
202       he = gethostbyname(x);
203       if (!he) {
204         free(name);
205         return VL_BADSERVER;
206       }
207       memcpy(&server_addr, he->h_addr, sizeof(server_addr));
208     }
209     partid = volutil_GetPartitionID(y);
210     if (partid < 0) {
211       free(name);
212       return VL_BADPARTITION;
213     }
214   }
215
216   /* Get tokens and set up a security object */
217   confdir = afsconf_Open(AFSCONF_CLIENTNAME);
218   if (!confdir) {
219     free(name);
220     return AFSCONF_NODB;
221   }
222   if (code = afsconf_GetLocalCell(confdir, sname.cell, MAXKTCNAMELEN)) {
223     free(name);
224     return code;
225   }
226   afsconf_Close(confdir);
227   strcpy(sname.name, "afs");
228   sname.instance[0] = 0;
229   code = ktc_GetToken(&sname, &token, sizeof(token), 0);
230   if (code) {
231     class = rxnull_NewClientSecurityObject();
232     index = 0;
233   } else {
234     class = rxkad_NewClientSecurityObject(rxkad_clear, &token.sessionKey,
235             token.kvno, token.ticketLen, token.ticket);
236     index = 2;
237   }
238
239   /* Figure out the volume ID, looking it up in the VLDB if neccessary.
240    * Also look up the server and partition, if they were not specified.
241    */
242   for (isnum = 1, y = name; *y; y++)
243     if (*y < '0' || *y > '9') isnum = 0;
244   if (isnum) {
245     volid = atoi(name);
246     if (!x) {
247       fprintf(stderr, "XXX: need to lookup volume by ID!\n");
248       exit(-1);
249     }
250   } else {
251     fprintf(stderr, "XXX: need to lookup volume by name!\n");
252     exit(-1);
253   }
254   free(name);
255
256   /* Establish a connection and start the call */
257   conn = rx_NewConnection(server_addr, htons(AFSCONF_VOLUMEPORT),
258                           VOLSERVICE_ID, class, index);
259   return xfopen_voldump(X, conn, partid, volid, date);
260 }