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