butc-xbsa-20040714
[openafs.git] / src / butc / butc_xbsa.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #ifdef xbsa
11
12 #include <afsconfig.h>
13 #include <afs/param.h>
14
15 RCSID
16     ("$Header$");
17
18 #include <sys/types.h>
19 #include <afs/stds.h>
20 #include <stdio.h>
21 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
22 #include <dlfcn.h>
23 #endif
24 #include <errno.h>
25 #include "butc_xbsa.h"
26 #include <afs/butx.h>
27 #include <afs/bubasics.h>
28
29 #include "error_macros.h"
30
31 extern int debugLevel;
32
33
34 char resourceType[20] = "LFS FILE SYSTEM";
35 #define GOODSTR(s) ((s)?(s):"<NULL>")
36
37 BSA_Int16(*XBSAInit) (BSA_UInt32 *, SecurityToken *, ObjectOwner *, char **);
38 BSA_Int16(*XBSABeginTxn) (BSA_UInt32);
39 BSA_Int16(*XBSAEndTxn) (BSA_UInt32, Vote);
40 BSA_Int16(*XBSATerminate) (BSA_UInt32);
41 BSA_Int16(*XBSAQueryObject) (BSA_UInt32, QueryDescriptor *,
42                              ObjectDescriptor *);
43 BSA_Int16(*XBSAGetObject) (BSA_UInt32, ObjectDescriptor *, DataBlock *);
44 BSA_Int16(*XBSAEndData) (BSA_UInt32);
45 BSA_Int16(*XBSACreateObject) (BSA_UInt32, ObjectDescriptor *, DataBlock *);
46 BSA_Int16(*XBSADeleteObject) (BSA_UInt32, CopyType, ObjectName *, CopyId *);
47 BSA_Int16(*XBSAMarkObjectInactive) (BSA_UInt32, ObjectName *);
48 BSA_Int16(*XBSASendData) (BSA_UInt32, DataBlock *);
49 BSA_Int16(*XBSAGetData) (BSA_UInt32, DataBlock *);
50 BSA_Int16(*XBSAQueryApiVersion) (ApiVersion *);
51 BSA_Int16(*XBSAGetEnvironment) (BSA_UInt32, ObjectOwner *, char **);
52
53
54 xbsa_error(int rc, struct butx_transactionInfo *info)
55 {
56     switch (rc) {
57     case BSA_RC_AUTHENTICATION_FAILURE:
58         ELog(0, "     XBSA: Authentication failure\n");
59         break;
60     case BSA_RC_INVALID_KEYWORD:
61         ELog(0, "     XBSA: A specified keyword is invalid\n");
62         break;
63     case BSA_RC_TOKEN_EXPIRED:
64         ELog(0, "     XBSA: The security token has expired\n");
65         break;
66     case ADSM_RC_PSWD_GEN:
67         if (XBSA_GET_SERVER_TYPE(info->serverType) == XBSA_SERVER_TYPE_ADSM) {
68             ELog(0, "     XBSA: Password generation is not supported\n");
69         }
70         break;
71     case BSA_RC_BAD_HANDLE:
72         ELog(0, "     XBSA: The handle is invalid, %d\n", info->bsaHandle);
73         break;
74     case BSA_RC_NO_MATCH:
75         ELog(0,
76              "     XBSA: There were no matches found for the specified object\n");
77         break;
78     case BSA_RC_MORE_DATA:
79         ELog(0, "     XBSA: There were more matches found than expected\n");
80         break;
81     case BSA_RC_NULL_OBJNAME:
82         ELog(0, "     XBSA: The object name is null\n");
83         break;
84     case BSA_RC_OBJNAME_TOO_LONG:
85         ELog(0, "     XBSA: The object name was longer than expected\n");
86         break;
87     case BSA_RC_DESC_TOO_LONG:
88         ELog(0,
89              "     XBSA: The description string was longer than expected\n");
90         break;
91     case BSA_RC_OBJINFO_TOO_LONG:
92         ELog(0,
93              "     XBSA: The object info string was longer than expected\n");
94         break;
95     case BSA_RC_ABORT_ACTIVE_NOT_FOUND:
96         ELog(0, "     XBSA: The specified object was not found\n");
97         break;
98     case BSA_RC_NULL_DATABLKPTR:
99         ELog(0, "     XBSA: The dataBlockPtr is null\n");
100         break;
101     case BSA_RC_INVALID_VOTE:
102         ELog(0, "     XBSA: The vote variable is invalid\n");
103         break;
104     }
105 }
106
107 /*
108  * Hook into the correct XBSA shared library.
109  * Set up the function pointers.
110  * Get the library version.
111  * XBSAQueryApiVersion
112  */
113 afs_int32
114 xbsa_MountLibrary(struct butx_transactionInfo *info, afs_int32 serverType)
115 {
116     void *dynlib;
117     int rc;
118
119     if (debugLevel > 98) {
120         printf("\nxbsa_MountLibraray\n");
121     }
122
123     switch (serverType) {
124     case XBSA_SERVER_TYPE_ADSM:
125 #if defined(AFS_AIX_ENV)
126         dynlib =
127             dlopen("/usr/lib/libXApi.a(bsashr10.o)",
128                    RTLD_NOW | RTLD_LOCAL | RTLD_MEMBER);
129         if (dynlib == NULL) {
130             dynlib =
131                 dlopen("/usr/lib/libXApi.a(xbsa.o)",
132                        RTLD_NOW | RTLD_LOCAL | RTLD_MEMBER);
133         }
134 #elif defined(AFS_SUN5_ENV)
135         dynlib = dlopen("/usr/lib/libXApi.so", RTLD_NOW | RTLD_LOCAL);
136 #else
137         dynlib = NULL;
138 #endif
139         break;
140     default:
141         ELog(0, "xbsa_MountLibrary: The serverType %d is not recognized\n",
142              serverType);
143         return (BUTX_INVALIDSERVERTYPE);
144         break;
145     }
146
147     if (dynlib == NULL) {
148         ELog(0,
149              "xbsa_MountLibrary: The dlopen call to load the XBSA shared library failed\n");
150         return (BUTX_NOLIBRARY);
151     }
152
153     memset(info, 0, sizeof(struct butx_transactionInfo));
154     XBSA_SET_SERVER_TYPE(info->serverType, serverType);
155
156 #if defined(AFS_AIX_ENV) || defined(AFS_SUN5_ENV)
157     XBSAInit = (BSA_Int16(*)
158                 (BSA_UInt32 *, SecurityToken *, ObjectOwner *,
159                  char **))dlsym((void *)dynlib, "BSAInit");
160     XBSABeginTxn =
161         (BSA_Int16(*)(BSA_UInt32)) dlsym((void *)dynlib, "BSABeginTxn");
162     XBSAEndTxn =
163         (BSA_Int16(*)(BSA_UInt32, Vote)) dlsym((void *)dynlib, "BSAEndTxn");
164     XBSATerminate =
165         (BSA_Int16(*)(BSA_UInt32)) dlsym((void *)dynlib, "BSATerminate");
166     XBSAQueryObject =
167         (BSA_Int16(*)(BSA_UInt32, QueryDescriptor *, ObjectDescriptor *))
168         dlsym((void *)dynlib, "BSAQueryObject");
169     XBSAGetObject =
170         (BSA_Int16(*)(BSA_UInt32, ObjectDescriptor *, DataBlock *))
171         dlsym((void *)dynlib, "BSAGetObject");
172     XBSAEndData =
173         (BSA_Int16(*)(BSA_UInt32)) dlsym((void *)dynlib, "BSAEndData");
174     XBSACreateObject =
175         (BSA_Int16(*)(BSA_UInt32, ObjectDescriptor *, DataBlock *))
176         dlsym((void *)dynlib, "BSACreateObject");
177     XBSAMarkObjectInactive =
178         (BSA_Int16(*)(BSA_UInt32, ObjectName *)) dlsym((void *)dynlib,
179                                                        "BSAMarkObjectInactive");
180     XBSADeleteObject =
181         (BSA_Int16(*)(BSA_UInt32, CopyType, ObjectName *, CopyId *))
182         dlsym((void *)dynlib, "BSADeleteObject");
183     XBSASendData =
184         (BSA_Int16(*)(BSA_UInt32, DataBlock *)) dlsym((void *)dynlib,
185                                                       "BSASendData");
186     XBSAGetData =
187         (BSA_Int16(*)(BSA_UInt32, DataBlock *)) dlsym((void *)dynlib,
188                                                       "BSAGetData");
189     XBSAQueryApiVersion =
190         (BSA_Int16(*)(ApiVersion *)) dlsym((void *)dynlib,
191                                            "BSAQueryApiVersion");
192     XBSAGetEnvironment =
193         (BSA_Int16(*)(BSA_UInt32, ObjectOwner *, char **))dlsym((void *)
194                                                                 dynlib,
195                                                                 "BSAGetEnvironment");
196
197     if (!XBSAInit || !XBSABeginTxn || !XBSAEndTxn || !XBSATerminate
198         || !XBSAQueryObject || !XBSAGetObject || !XBSAEndData
199         || !XBSACreateObject || !XBSADeleteObject || !XBSAMarkObjectInactive
200         || !XBSASendData || !XBSAGetData || !XBSAQueryApiVersion
201         || !XBSAGetEnvironment) {
202         ELog(0,
203              "xbsa_MountLibrary: The dlopen call to load the XBSA shared library failed\n");
204         return (BUTX_NOLIBRARY);
205     }
206
207     XBSAQueryApiVersion(&(info->apiVersion));
208 #endif
209
210     /*
211      * Verify the API version
212      */
213     if ((info->apiVersion.version == XBSA_TS_VERSION)
214         && (info->apiVersion.release == XBSA_TS_RELEASE)) {
215         /* XOPEN Techincal Standard Level! 
216          * We are coded to the Preliminary Spec!  Time to go boom!
217          */
218         ELog(0,
219              "xbsa_MountLibrary: The XBSAQueryApiVersion call returned an incompatible version, %d %d %d\n",
220              info->apiVersion.version, info->apiVersion.release,
221              info->apiVersion.level);
222         return (BUTX_INVALIDVERSION);
223     }
224
225     switch (XBSA_GET_SERVER_TYPE(info->serverType)) {
226     case XBSA_SERVER_TYPE_ADSM:
227         if ((info->apiVersion.version > XBSA_ADSM_NO_MULT_SERVER_VERSION)
228             || (info->apiVersion.version == XBSA_ADSM_NO_MULT_SERVER_VERSION
229                 && info->apiVersion.release >
230                 XBSA_ADSM_NO_MULT_SERVER_RELEASE)
231             || (info->apiVersion.version == XBSA_ADSM_NO_MULT_SERVER_VERSION
232                 && info->apiVersion.release ==
233                 XBSA_ADSM_NO_MULT_SERVER_RELEASE
234                 && info->apiVersion.level > XBSA_ADSM_NO_MULT_SERVER_LEVEL)) {
235
236             /* This version contains the fixes to allow multiple servers */
237             info->serverType |= XBSA_SERVER_FLAG_MULTIPLE;
238         } else {
239             /* This is an older version of ADSM prior to the fix to
240              * allow multiple servers.
241              */
242             info->serverType |= XBSA_SERVER_FLAG_NONE;
243         }
244         break;
245     }
246
247     return (XBSA_SUCCESS);
248
249 }
250
251 /*
252  * Set up the connection to the XBSA Server.
253  * BSAInit
254  * BSAGetEnvironment
255  */
256 afs_int32
257 xbsa_Initialize(struct butx_transactionInfo * info, char *bsaObjectOwner,
258                 char *appObjectOwner, char *secToken, char *serverName)
259 {
260     char envStrs[XBSA_NUM_ENV_STRS][BSA_MAX_DESC];
261     char *envP[XBSA_NUM_ENV_STRS + 1];
262     char *ADSMMaxObject = "TSMMAXOBJ=";
263     char *ADSMServer = "TSMSRVR=";
264     char *tempStrPtr;
265     int i;
266     int rc;
267
268     if (debugLevel > 98) {
269         printf("\nxbsa_Initialize bsaObjectOwner='%s' appObjectOwner='%s' "
270                "secToken=xxxxxx servername='%s'\n", GOODSTR(bsaObjectOwner),
271                GOODSTR(appObjectOwner), GOODSTR(serverName));
272     }
273
274     if (info->bsaHandle != 0) {
275         /* We already have a handle */
276         ELog(0,
277              "xbsa_Initialize: The dlopen call to load the XBSA shared library failed\n");
278         return (BUTX_ILLEGALINIT);
279     }
280
281     /*
282      * The XBSAGetEnvironment function is supposed to return the
283      * the serverName to use.  However, it is returning the tcpserveraddress
284      * instead.  So, we can't count on this function to properly fill it
285      * in.  So, until that get fixed.  The serverName will have to be filled
286      * in by the callers of this function (butc).
287      */
288
289     /* Initialize the environment strings */
290     for (i = 0; i < XBSA_NUM_ENV_STRS; i++)
291         envP[i] = envStrs[i];
292     envP[XBSA_NUM_ENV_STRS] = NULL;
293
294     /* The environment variables are specific to the server type */
295     switch (XBSA_GET_SERVER_TYPE(info->serverType)) {
296     case XBSA_SERVER_TYPE_ADSM:
297         if (serverName) {
298             if (strlen(serverName) >= BSA_MAX_DESC) {
299                 ELog(0,
300                      "xbsa_Initialize: The serverName was not specified\n");
301                 return (BUTX_INVALIDSERVERNAME);
302             }
303             strcpy(info->serverName, serverName);
304             strcpy(envP[0], ADSMServer);
305             tempStrPtr = envP[0];
306             tempStrPtr = tempStrPtr + strlen(ADSMServer);
307             strcat(tempStrPtr, serverName);
308             envP[1] = NULL;
309             envP[0] = NULL;     /* Hack for TSM V5 */
310         } else {
311             envP[0] = NULL;
312             ELog(0, "xbsa_Initialize: The serverName was not specified\n");
313             return (BUTX_INVALIDSERVERNAME);
314         }
315         break;
316     default:
317         ELog(0, "xbsa_Initialize: The serverType %d is not recognized\n",
318              XBSA_GET_SERVER_TYPE(info->serverType));
319         return (BUTX_INVALIDSERVERTYPE);
320         break;
321     }
322
323     if (bsaObjectOwner) {
324         if (strlen(bsaObjectOwner) >= BSA_MAX_BSAOBJECT_OWNER) {
325             ELog(0,
326                  "xbsa_Initialize: The bsaObjectOwner is too long; size = %d; name = %s\n",
327                  strlen(bsaObjectOwner), bsaObjectOwner);
328             return (BUTX_INVALIDBSANAME);
329         }
330         strcpy(info->objOwner.bsaObjectOwner, bsaObjectOwner);
331     } else {
332         info->objOwner.bsaObjectOwner[0] = NULL;
333     }
334
335     if (appObjectOwner) {
336         if (strlen(appObjectOwner) >= BSA_MAX_APPOBJECT_OWNER) {
337             ELog(0,
338                  "xbsa_Initialize: The appObjectOwner is too long; size = %d; name = %s\n",
339                  strlen(appObjectOwner), appObjectOwner);
340             return (BUTX_INVALIDAPPNAME);
341         }
342         strcpy(info->objOwner.appObjectOwner, appObjectOwner);
343     } else {
344         info->objOwner.appObjectOwner[0] = NULL;
345     }
346
347     if (secToken) {
348         if (strlen(secToken) >= BSA_MAX_TOKEN_SIZE) {
349             ELog(0,
350                  "xbsa_Initialize: The secToken is too long; size = %d; name = %s\n",
351                  strlen(secToken), secToken);
352             return (BUTX_INVALIDSECTOKEN);
353         }
354         strcpy(info->secToken, secToken);
355     } else {
356         info->secToken[0] = NULL;
357     }
358
359     rc = (int)XBSAInit(&(info->bsaHandle), &(info->secToken),
360                        &(info->objOwner), envP);
361     if (rc != BSA_RC_SUCCESS) {
362         ELog(0, "xbsa_Initialize: The XBSAInit call failed with %d\n", rc);
363         xbsa_error(rc, info);
364         return (BUTX_INITFAIL);
365     }
366
367     /* Initialize the environment strings */
368     for (i = 0; i < XBSA_NUM_ENV_STRS; i++)
369         envP[i] = envStrs[i];
370     envP[XBSA_NUM_ENV_STRS] = NULL;
371
372     rc = (int)XBSAGetEnvironment(info->bsaHandle, &info->objOwner, envP);
373     if (rc != BSA_RC_SUCCESS) {
374         ELog(0,
375              "xbsa_Initialize: The XBSAGetEnvironment call failed with %d\n",
376              rc);
377         xbsa_error(rc, info);
378         return (BUTX_GETENVFAIL);
379     }
380
381  info->maxObjects = 255; /* Hack for ADSM V5: unclear what this actually means... */
382
383     switch (XBSA_GET_SERVER_TYPE(info->serverType)) {
384     case XBSA_SERVER_TYPE_ADSM:
385         for (i = 0; i < XBSA_NUM_ENV_STRS; i++) {
386             if (strncmp(envP[i], ADSMMaxObject, sizeof(ADSMMaxObject)) == 0) {
387                 tempStrPtr = envP[i];
388                 tempStrPtr = tempStrPtr + strlen(ADSMMaxObject);
389                 info->maxObjects = strtol(tempStrPtr, NULL, 10);
390                 if (info->maxObjects <= 0) {
391                     ELog(0,
392                          "xbsa_Initialize: The XBSAGetEnvironment call returned an invalid value for MAXOBJ %d\n",
393                          info->maxObjects);
394                     return (BUTX_GETENVFAIL);
395                 }
396             }
397         }
398         if (info->maxObjects == 0) {
399             ELog(0,
400                  "xbsa_Initialize: The XBSAGetEnvironment call failed to return the MAXOBJ string\n");
401             return (BUTX_GETENVFAIL);
402         }
403         break;
404     }
405
406     return (XBSA_SUCCESS);
407 }
408
409 /*
410  * Create a transaction
411  * BSABeginTxn
412  */
413 afs_int32
414 xbsa_BeginTrans(struct butx_transactionInfo * info)
415 {
416     int rc;
417
418     if (debugLevel > 98) {
419         printf("\nxbsa_BeginTrans\n");
420         printf
421             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
422              GOODSTR(info->serverName),
423              GOODSTR(info->objOwner.bsaObjectOwner),
424              GOODSTR(info->objOwner.appObjectOwner));
425     }
426
427     if (info->bsaHandle == 0) {
428         /* We haven't initialized yet! */
429         ELog(0, "xbsa_BeginTrans: No current handle, butx not initialized\n");
430         return (BUTX_NOHANDLE);
431     }
432
433     rc = (int)XBSABeginTxn(info->bsaHandle);
434     if (rc != BSA_RC_SUCCESS) {
435         ELog(0, "xbsa_BeginTrans: The XBSABeginTxn call failed with %d\n",
436              rc);
437         xbsa_error(rc, info);
438         return (BUTX_BEGINTXNFAIL);
439     }
440
441     info->numObjects = 0;
442     return (XBSA_SUCCESS);
443 }
444
445 /*
446  * End the current transaction
447  * BSAEndTxn
448  */
449 afs_int32
450 xbsa_EndTrans(struct butx_transactionInfo * info)
451 {
452     int rc;
453
454     if (debugLevel > 98) {
455         printf("\nxbsa_EndTrans\n");
456         printf
457             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
458              GOODSTR(info->serverName),
459              GOODSTR(info->objOwner.bsaObjectOwner),
460              GOODSTR(info->objOwner.appObjectOwner));
461     }
462
463     if (info->bsaHandle == 0) {
464         /* We haven't initialized yet! */
465         ELog(0, "xbsa_EndTrans: No current handle, butx not initialized\n");
466         return (BUTX_NOHANDLE);
467     }
468
469     /* terminate the transaction */
470     rc = (int)XBSAEndTxn(info->bsaHandle, BSAVote_COMMIT);
471     if (rc != BSA_RC_SUCCESS) {
472         ELog(0, "xbsa_EndTrans: The XBSAEndTxn call failed with %d\n", rc);
473         xbsa_error(rc, info);
474         return (BUTX_ENDTXNFAIL);
475     }
476     return (XBSA_SUCCESS);
477 }
478
479 /*
480  * Terminate the connection to the XBSA Server.
481  * End the transaction.
482  * BSATerminate
483  */
484 afs_int32
485 xbsa_Finalize(struct butx_transactionInfo * info)
486 {
487     int rc;
488
489     if (debugLevel > 98) {
490         printf("\nxbsa_Finalize\n");
491         printf
492             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
493              GOODSTR(info->serverName),
494              GOODSTR(info->objOwner.bsaObjectOwner),
495              GOODSTR(info->objOwner.appObjectOwner));
496     }
497
498     if (info->bsaHandle == 0) {
499         /* We haven't initialized yet! */
500         ELog(0, "xbsa_Finalize: No current handle, butx not initialized\n");
501         return (BUTX_NOHANDLE);
502     }
503
504     /* terminate the session */
505     rc = (int)XBSATerminate(info->bsaHandle);
506     if (rc != BSA_RC_SUCCESS) {
507         ELog(0, "The XBSATerminate call failed with %d\n", rc);
508         xbsa_error(rc, info);
509         return (BUTX_TERMFAIL);
510     }
511
512     info->bsaHandle = 0;
513     return (XBSA_SUCCESS);
514 }
515
516 /*
517  * Query for the object we are looking for.
518  * BSAQueryObject
519  */
520 afs_int32
521 xbsa_QueryObject(struct butx_transactionInfo * info, char *objectSpaceName,
522                  char *pathName)
523 {
524     int rc;
525     QueryDescriptor queryDescriptor;
526
527     if (debugLevel > 98) {
528         printf("\nxbsa_QueryObject objectSpaceName='%s' pathnName='%s'\n",
529                GOODSTR(objectSpaceName), GOODSTR(pathName));
530         printf
531             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
532              GOODSTR(info->serverName),
533              GOODSTR(info->objOwner.bsaObjectOwner),
534              GOODSTR(info->objOwner.appObjectOwner));
535     }
536
537     if (info->bsaHandle == 0) {
538         /* We haven't initialized yet! */
539         ELog(0,
540              "xbsa_QueryObject: No current handle, butx not initialized\n");
541         return (BUTX_NOHANDLE);
542     }
543
544     /* Initialize the query for our dump name */
545
546     if (objectSpaceName) {
547         if (strlen(objectSpaceName) >= BSA_MAX_OSNAME) {
548             ELog(0,
549                  "xbsa_QueryObject: The objectSpaceName is too long; size = %d; name = %s\n",
550                  strlen(objectSpaceName), objectSpaceName);
551             return (BUTX_INVALIDOBJECTSPNAME);
552         }
553         strcpy(queryDescriptor.objName.objectSpaceName, objectSpaceName);
554     } else {
555         queryDescriptor.objName.objectSpaceName[0] = NULL;
556     }
557
558     if (pathName) {
559         if (strlen(pathName) >= BSA_MAX_PATHNAME) {
560             ELog(0,
561                  "xbsa_QueryObject: The pathName is too long; size = %d; name = %s\n",
562                  strlen(pathName), pathName);
563             return (BUTX_INVALIDPATHNAME);
564         }
565         strcpy(queryDescriptor.objName.pathName, pathName);
566     } else {
567         queryDescriptor.objName.pathName[0] = NULL;
568     }
569
570     queryDescriptor.owner = info->objOwner;
571     queryDescriptor.copyType = BSACopyType_BACKUP;
572     strcpy(queryDescriptor.lGName, "");
573     strcpy(queryDescriptor.cGName, "");
574     strcpy(queryDescriptor.resourceType, "");
575     queryDescriptor.objectType = BSAObjectType_FILE;
576     queryDescriptor.status = BSAObjectStatus_ACTIVE;
577     strcpy(queryDescriptor.desc, "");
578
579     rc = (int)XBSAQueryObject(info->bsaHandle, &queryDescriptor,
580                               &info->curObject);
581     if (rc == BSA_RC_NO_MORE_DATA)
582         rc = BSA_RC_SUCCESS;    /* This is actually a success! */
583     if (rc != BSA_RC_SUCCESS) {
584         ELog(0, "xbsa_QueryObject: The xBSAQueryObject call failed with %d\n",
585              rc);
586         xbsa_error(rc, info);
587         return (BUTX_QUERYFAIL);
588     }
589     return (XBSA_SUCCESS);
590 }
591
592 /*
593  * Locate the correct object on the server and then make the call to
594  * get the object descriptor so we can begin the transfer of data.
595  * BSAGetObject
596  */
597 afs_int32
598 xbsa_ReadObjectBegin(struct butx_transactionInfo * info, char *dataBuffer,
599                      afs_int32 bufferSize, afs_int32 * count,
600                      afs_int32 * endOfData)
601 {
602     int rc;
603     DataBlock dataBlock;
604
605     if (debugLevel > 98) {
606         printf("\nxbsa_ReadObjectBegin %d Bytes\n", bufferSize);
607         printf
608             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
609              GOODSTR(info->serverName),
610              GOODSTR(info->objOwner.bsaObjectOwner),
611              GOODSTR(info->objOwner.appObjectOwner));
612     }
613
614     if (info->bsaHandle == 0) {
615         /* We haven't initialized yet! */
616         ELog(0,
617              "xbsa_ReadObjectBegin: No current handle, butx not initialized\n");
618         return (BUTX_NOHANDLE);
619     }
620
621     if ((bufferSize < 0) || (bufferSize > XBSAMAXBUFFER)) {
622         ELog(0, "xbsa_ReadObjectBegin: The bufferSize %d is invalid\n",
623              bufferSize);
624         return (BUTX_INVALIDBUFFERSIZE);
625     }
626
627     if (dataBuffer == NULL) {
628         ELog(0, "xbsa_ReadObjectBegin: The dataBuffer is NULL\n");
629         return (BUTX_INVALIDDATABUFFER);
630     }
631
632     dataBlock.bufferLen = (BSA_UInt16) bufferSize;
633     dataBlock.numBytes = (BSA_UInt16) 0;
634     dataBlock.bufferPtr = dataBuffer;
635     *endOfData = 0;
636
637     rc = (int)XBSAGetObject(info->bsaHandle, &info->curObject, &dataBlock);
638     if ((rc != BSA_RC_MORE_DATA) && (rc != BSA_RC_NO_MORE_DATA)) {
639         ELog(0,
640              "xbsa_ReadObjectBegin: The XBSAGetObject call failed with %d\n",
641              rc);
642         xbsa_error(rc, info);
643         return (BUTX_GETOBJFAIL);
644     }
645     *count = dataBlock.numBytes;
646     if (rc == BSA_RC_NO_MORE_DATA)
647         *endOfData = 1;
648     return (XBSA_SUCCESS);
649 }
650
651
652 /*
653  * Tell the XBSA Server that this is the end of Data for this object.
654  * BSAEndData()
655  */
656 afs_int32
657 xbsa_ReadObjectEnd(struct butx_transactionInfo * info)
658 {
659     int rc;
660
661     if (debugLevel > 98) {
662         printf("\nxbsa_ReadObjectEnd\n");
663         printf
664             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
665              GOODSTR(info->serverName),
666              GOODSTR(info->objOwner.bsaObjectOwner),
667              GOODSTR(info->objOwner.appObjectOwner));
668     }
669
670     if (info->bsaHandle == 0) {
671         /* We haven't initialized yet! */
672         ELog(0,
673              "xbsa_ReadObjectEnd: No current handle, butx not initialized\n");
674         return (BUTX_NOHANDLE);
675     }
676     rc = (int)XBSAEndData(info->bsaHandle);
677     if (rc != BSA_RC_SUCCESS) {
678         ELog(0, "xbsa_ReadObjectEnd: XBSAEndData call failed with %d\n", rc);
679         xbsa_error(rc, info);
680         return (BUTX_ENDDATAFAIL);
681     }
682     return (XBSA_SUCCESS);
683 }
684
685
686 /*
687  * Create the XBSA Backup Copy Object.
688  * BSACreateObject
689  */
690 afs_int32
691 xbsa_WriteObjectBegin(struct butx_transactionInfo * info,
692                       char *objectSpaceName, char *pathName, char *lGName,
693                       afs_hyper_t estimatedSize, char *objectDescription,
694                       char *objectInfo)
695 {
696     int rc;
697     int length;
698     DataBlock dataBlock;
699
700     if (debugLevel > 98) {
701         printf
702             ("\nxbsa_WriteObjectBegin objectSpacename='%s' pathName='%s' lGName='%s' "
703              "estimatesSize='0x%x%08x objectDescription='%s' objectInfo='%s'\n",
704              GOODSTR(objectSpaceName), GOODSTR(pathName), GOODSTR(lGName),
705              hgethi(estimatedSize), hgetlo(estimatedSize),
706              GOODSTR(objectDescription), GOODSTR(objectInfo));
707         printf
708             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
709              GOODSTR(info->serverName),
710              GOODSTR(info->objOwner.bsaObjectOwner),
711              GOODSTR(info->objOwner.appObjectOwner));
712     }
713
714     if (info->bsaHandle == 0) {
715         /* We haven't initialized yet! */
716         ELog(0,
717              "xbsa_WriteObjectBegin: No current handle, butx not initialized\n");
718         return (BUTX_NOHANDLE);
719     }
720
721     if (objectSpaceName) {
722         if (strlen(objectSpaceName) >= BSA_MAX_OSNAME) {
723             ELog(0,
724                  "xbsa_WriteObjectBegin: The objectSpaceName is too long; size = %d; name = %s\n",
725                  strlen(objectSpaceName), objectSpaceName);
726             return (BUTX_INVALIDOBJECTSPNAME);
727         }
728         strcpy(info->curObject.objName.objectSpaceName, objectSpaceName);
729     } else {
730         info->curObject.objName.objectSpaceName[0] = NULL;
731     }
732
733     if (pathName) {
734         if (strlen(pathName) >= BSA_MAX_PATHNAME) {
735             ELog(0,
736                  "xbsa_WriteObjectBegin: The pathName is too long; size = %d; name = %s\n",
737                  strlen(pathName), pathName);
738             return (BUTX_INVALIDPATHNAME);
739         }
740         strcpy(info->curObject.objName.pathName, pathName);
741     } else {
742         info->curObject.objName.pathName[0] = NULL;
743     }
744
745     if (lGName) {
746         if (strlen(lGName) >= BSA_MAX_LG_NAME) {
747             ELog(0,
748                  "xbsa_WriteObjectBegin: The lGName is too long; size = %d; name = %s\n",
749                  strlen(lGName), lGName);
750             return (BUTX_INVALIDLGNAME);
751         }
752         strcpy(info->curObject.lGName, lGName);
753     } else {
754         info->curObject.lGName[0] = NULL;
755     }
756
757     if (objectDescription) {
758         if (((XBSA_GET_SERVER_TYPE(info->serverType) == XBSA_SERVER_TYPE_ADSM)
759              && (strlen(objectDescription) >= ADSM_MAX_DESC))
760             ||
761             ((XBSA_GET_SERVER_TYPE(info->serverType) != XBSA_SERVER_TYPE_ADSM)
762              && (strlen(objectDescription) >= BSA_MAX_DESC))) {
763             ELog(0,
764                  "xbsa_WriteObjectBegin: The objectDescription is too long; size = %d; name = %s\n",
765                  strlen(objectDescription), objectDescription);
766             return (BUTX_INVALIDOBJDESC);
767         }
768         strcpy(info->curObject.desc, objectDescription);
769     } else {
770         info->curObject.desc[0] = NULL;
771     }
772
773     if (objectInfo) {
774         if (((XBSA_GET_SERVER_TYPE(info->serverType) == XBSA_SERVER_TYPE_ADSM)
775              && (strlen(objectInfo) >= ADSM_MAX_OBJINFO))
776             ||
777             ((XBSA_GET_SERVER_TYPE(info->serverType) != XBSA_SERVER_TYPE_ADSM)
778              && (strlen(objectInfo) >= BSA_MAX_OBJINFO))) {
779             ELog(0,
780                  "xbsa_WriteObjectBegin: The objectInfo is too long; size = %d; name = %s\n",
781                  strlen(objectInfo), objectInfo);
782             return (BUTX_INVALIDOBJINFO);
783         }
784         strcpy(info->curObject.objectInfo, objectInfo);
785     } else {
786         info->curObject.objectInfo[0] = NULL;
787     }
788
789     if (info->numObjects == info->maxObjects) {
790         /* If we've used up Max Objects we must start a new transaction. */
791         rc = (int)xbsa_EndTrans(info);
792         if (rc != XBSA_SUCCESS) {
793             return (rc);
794         }
795         rc = (int)xbsa_BeginTrans(info);
796         if (rc != XBSA_SUCCESS) {
797             return (rc);
798         }
799     }
800
801     dataBlock.bufferLen = (BSA_UInt16) 0;
802     dataBlock.numBytes = (BSA_UInt16) 0;
803     dataBlock.bufferPtr = 0;
804
805     info->curObject.Owner = info->objOwner;
806     info->curObject.copyType = BSACopyType_BACKUP;
807     info->curObject.size.left = hgethi(estimatedSize);
808     info->curObject.size.right = hgetlo(estimatedSize);
809     info->curObject.objectType = BSAObjectType_FILE;
810     strcpy(info->curObject.resourceType, resourceType);
811
812     rc = (int)XBSACreateObject(info->bsaHandle, &info->curObject, &dataBlock);
813     if (rc != BSA_RC_SUCCESS) {
814         ELog(0,
815              "xbsa_WriteObjectBegin: The XBSACreateObject call failed with %d\n",
816              rc);
817         xbsa_error(rc, info);
818         return (BUTX_CREATEOBJFAIL);
819     }
820
821     info->numObjects++;
822
823     return (XBSA_SUCCESS);
824 }
825
826 /*
827  * Delete a backup object from the server
828  * BSAMarkObjectInactive()
829  * BSADeleteObject()
830  */
831 afs_int32
832 xbsa_DeleteObject(struct butx_transactionInfo * info, char *objectSpaceName,
833                   char *pathName)
834 {
835     int rc;
836     ObjectName objectName;
837
838     if (debugLevel > 98) {
839         printf("\nxbsa_DeleteObject objectSpacename='%s' pathName='%s'\n",
840                GOODSTR(objectSpaceName), GOODSTR(pathName));
841         printf
842             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
843              GOODSTR(info->serverName),
844              GOODSTR(info->objOwner.bsaObjectOwner),
845              GOODSTR(info->objOwner.appObjectOwner));
846     }
847
848     if (info->bsaHandle == 0) {
849         /* We haven't initialized yet! */
850         ELog(0,
851              "xbsa_DeleteObject: No current handle, butx not initialized\n");
852         return (BUTX_NOHANDLE);
853     }
854
855     if (objectSpaceName) {
856         if (strlen(objectSpaceName) >= BSA_MAX_OSNAME) {
857             ELog(0,
858                  "xbsa_DeleteObject: The objectSpaceName is too long; size = %d; name = %s\n",
859                  strlen(objectSpaceName), objectSpaceName);
860             return (BUTX_INVALIDOBJECTSPNAME);
861         }
862         strcpy(objectName.objectSpaceName, objectSpaceName);
863     } else {
864         objectName.objectSpaceName[0] = NULL;
865     }
866
867     if (pathName) {
868         if (strlen(pathName) >= BSA_MAX_PATHNAME) {
869             ELog(0, "xbsa_DeleteObject: strlen(pathName), pathName\n",
870                  strlen(pathName), pathName);
871             return (BUTX_INVALIDPATHNAME);
872         }
873         strcpy(objectName.pathName, pathName);
874     } else {
875         objectName.pathName[0] = NULL;
876     }
877
878     rc = (int)XBSAMarkObjectInactive(info->bsaHandle, &objectName);
879     if (rc != BSA_RC_SUCCESS) {
880         ELog(0,
881              "xbsa_DeleteObject: XBSAMarkObjectInactive call failed with %d\n",
882              rc);
883         xbsa_error(rc, info);
884         return ((rc ==
885                  BSA_RC_ABORT_ACTIVE_NOT_FOUND) ? BUTX_DELETENOVOL :
886                 BUTX_DELETEOBJFAIL);
887     }
888
889     return (XBSA_SUCCESS);
890 }
891
892 /*
893  * Tell the XBSA Server that this is the end of Data for this object.
894  * BSAEndData()
895  */
896 afs_int32
897 xbsa_WriteObjectEnd(struct butx_transactionInfo * info)
898 {
899     int rc;
900
901     if (debugLevel > 98) {
902         printf("\nxbsa_WriteObjectEnd\n");
903         printf
904             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
905              GOODSTR(info->serverName),
906              GOODSTR(info->objOwner.bsaObjectOwner),
907              GOODSTR(info->objOwner.appObjectOwner));
908     }
909
910     if (info->bsaHandle == 0) {
911         /* We haven't initialized yet! */
912         ELog(0,
913              "xbsa_WriteObjectEnd: No current handle, butx not initialized\n");
914         return (BUTX_NOHANDLE);
915     }
916     rc = (int)XBSAEndData(info->bsaHandle);
917     if (rc != BSA_RC_SUCCESS) {
918         ELog(0, "xbsa_WriteObjectEnd: XBSAEndData call failed with %d\n", rc);
919         xbsa_error(rc, info);
920         return (BUTX_ENDDATAFAIL);
921     }
922
923     return (XBSA_SUCCESS);
924 }
925
926
927 /*
928  * Write the fileset data to the XBSA server
929  * BSASendData
930  */
931 afs_int32
932 xbsa_WriteObjectData(struct butx_transactionInfo * info, char *dataBuffer,
933                      afs_int32 bufferSize, afs_int32 * count)
934 {
935     int rc;
936     DataBlock dataBlock;
937
938     if (debugLevel > 98) {
939         printf("\nxbsa_WriteObjectData %d Bytes\n", bufferSize);
940         printf
941             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
942              GOODSTR(info->serverName),
943              GOODSTR(info->objOwner.bsaObjectOwner),
944              GOODSTR(info->objOwner.appObjectOwner));
945     }
946
947     if (info->bsaHandle == 0) {
948         /* We haven't initialized yet! */
949         ELog(0,
950              "xbsa_WriteObjectData: No current handle, butx not initialized\n");
951         return (BUTX_NOHANDLE);
952     }
953
954     if ((bufferSize < 0) || (bufferSize > XBSAMAXBUFFER)) {
955         ELog(0, "xbsa_WriteObjectData: The bufferSize %d is invalid\n",
956              bufferSize);
957         return (BUTX_INVALIDBUFFERSIZE);
958     }
959
960     if (dataBuffer == NULL) {
961         ELog(0, "xbsa_WriteObjectData: The dataBuffer is NULL\n");
962         return (BUTX_INVALIDDATABUFFER);
963     }
964
965     dataBlock.bufferPtr = dataBuffer;
966     dataBlock.bufferLen = (BSA_UInt16) bufferSize;
967     dataBlock.numBytes = (BSA_UInt16) 0;
968
969     rc = (int)XBSASendData(info->bsaHandle, &dataBlock);
970     if (rc != BSA_RC_SUCCESS) {
971         ELog(0, "xbsa_WriteObjectData: XBSAEndData call failed with %d\n",
972              rc);
973         xbsa_error(rc, info);
974         return (BUTX_SENDDATAFAIL);
975     }
976     *count = dataBlock.numBytes;
977     return (XBSA_SUCCESS);
978 }
979
980
981 /*
982  * Read the fileset data from the XBSA server
983  * BSAGetData
984  */
985 afs_int32
986 xbsa_ReadObjectData(struct butx_transactionInfo * info, char *dataBuffer,
987                     afs_int32 bufferSize, afs_int32 * count,
988                     afs_int32 * endOfData)
989 {
990     int rc;
991     DataBlock dataBlock;
992
993     if (debugLevel > 98) {
994         printf("\nxbsa_ReadObjectData %d Bytes\n", bufferSize);
995         printf
996             ("serverName='%s' ; bsaObjectOwner='%s' ; appObjectOwner='%s' ; sectoken=xxxxxx\n",
997              GOODSTR(info->serverName),
998              GOODSTR(info->objOwner.bsaObjectOwner),
999              GOODSTR(info->objOwner.appObjectOwner));
1000     }
1001
1002     if (info->bsaHandle == 0) {
1003         /* We haven't initialized yet! */
1004         ELog(0,
1005              "xbsa_ReadObjectData: No current handle, butx not initialized\n");
1006         return (BUTX_NOHANDLE);
1007     }
1008
1009     if ((bufferSize < 0) || (bufferSize > XBSAMAXBUFFER)) {
1010         ELog(0, "xbsa_ReadObjectData: The bufferSize %d is invalid\n",
1011              bufferSize);
1012         return (BUTX_INVALIDBUFFERSIZE);
1013     }
1014
1015     if (dataBuffer == NULL) {
1016         ELog(0, "xbsa_ReadObjectData: The dataBuffer is NULL\n");
1017         return (BUTX_INVALIDDATABUFFER);
1018     }
1019
1020     dataBlock.bufferLen = (BSA_UInt16) bufferSize;
1021     dataBlock.numBytes = (BSA_UInt16) 0;
1022     dataBlock.bufferPtr = dataBuffer;
1023     *endOfData = 0;
1024
1025     rc = (int)XBSAGetData(info->bsaHandle, &dataBlock);
1026     if ((rc != BSA_RC_MORE_DATA) && (rc != BSA_RC_NO_MORE_DATA)) {
1027         ELog(0, "xbsa_ReadObjectData: XBSAGetData call failed with %d\n", rc);
1028         xbsa_error(rc, info);
1029         return (BUTX_GETDATAFAIL);
1030     }
1031     *count = dataBlock.numBytes;
1032     if (rc == BSA_RC_NO_MORE_DATA)
1033         *endOfData = 1;
1034     return (XBSA_SUCCESS);
1035 }
1036 #endif /*xbsa */