The Perl Toolchain Summit needs more sponsors. If your company depends on Perl, please support this very important event.
/*
 * If you get compilation errors and your SamFS version is somewhat
 * dated, you could try to uncomment the definition of OLS_SAMFS. The
 * author does not have access to SamFS anymore, let alone older
 * versions, so he can't check when OLD_SAMFS should be set. He would
 * definitely appreciate a mail describing the problems you encountered.
 */

/*
#define OLD_SAMFS
 */

#include "EXTERN.h"
#include "perl.h"
#include "XSUB.h"

/* Avoid clash with library. */
extern char *dev_state[];
#define DEV_NM_HERE
#include <devstat.h>

#include <stat.h>
#include <rminfo.h>
#include <version.h>
#include <lib.h>
#include <catalog.h>

/* Not declared in early SamFS header files. */
char *sam_devstr(uint_t status);

#include "const-c.inc"

char buff[21];

char *
ull2s(u_longlong_t value)
{
	sprintf(buff, "%llu", value);
	return buff;
}

void
sam_stat2av(struct sam_stat *info, AV *av)
{
        int i;
        AV *copies;

	av_store(av,  0, newSViv(info->st_dev));
	av_store(av,  1, newSViv(info->st_ino));
	av_store(av,  2, newSViv(info->st_mode));
	av_store(av,  3, newSViv(info->st_nlink));
	av_store(av,  4, newSViv(info->st_uid));
	av_store(av,  5, newSViv(info->st_gid));
	av_store(av,  6, newSViv(info->rdev));
	av_store(av,  7, newSVpv(ull2s(info->st_size), 0));
	av_store(av,  8, newSViv(info->st_atime));
	av_store(av,  9, newSViv(info->st_mtime));
	av_store(av, 10, newSViv(info->st_ctime));
	av_store(av, 11, newSViv(512));		/* blksize */
	av_store(av, 12, newSVpv(ull2s(info->st_blocks), 0));
	av_store(av, 13, newSViv(info->attr));
	av_store(av, 14, newSViv(info->attribute_time));
	av_store(av, 15, newSViv(info->creation_time));
	av_store(av, 16, newSViv(info->residence_time));
	av_store(av, 17, newSViv(info->cs_algo));
	av_store(av, 18, newSViv(info->flags));
	av_store(av, 19, newSViv(info->gen));
	av_store(av, 20, newSViv(info->partial_size));
        copies = newAV();
        av_extend(av, MAX_ARCHIVE);
	av_store(av, 21, newRV_noinc((SV*)copies));
	for (i=0; i<MAX_ARCHIVE; i++) {
                AV *av = newAV();
                av_store(copies, i, newRV_noinc((SV*)av));
                av_extend(av, 7);
		av_store(av, 0, newSViv(info->copy[i].flags));
	        av_store(av, 1, newSViv(info->copy[i].n_vsns));
		av_store(av, 2, newSViv(info->copy[i].creation_time));
	        av_store(av, 3, newSVpv(ull2s(info->copy[i].position), 0));
                av_store(av, 4, newSViv(info->copy[i].offset));
		av_store(av, 5, newSVpv(info->copy[i].media, 0));
	        av_store(av, 6, newSVpv(info->copy[i].vsn, 0));
        }
	av_store(av, 22, newSViv(info->stripe_width));
	av_store(av, 23, newSViv(info->stripe_group));
	av_store(av, 24, newSViv(info->segment_size));
	av_store(av, 25, newSViv(info->segment_number));
	av_store(av, 26, newSViv(info->stage_ahead));
	av_store(av, 27, newSViv(info->admin_id));
	av_store(av, 28, newSViv(info->allocahead));
}

MODULE = Filesys::SamFS		PACKAGE = Filesys::SamFS		PREFIX = sam_

PROTOTYPES: DISABLE

INCLUDE: const-xs.inc

char *
sam_FIXV()
CODE:
	RETVAL = SAM_FIXV;
OUTPUT:
	RETVAL

char *
sam_MAJORV()
CODE:
	RETVAL = SAM_MAJORV;
OUTPUT:
	RETVAL

char *
sam_MINORV()
CODE:
	RETVAL = SAM_MINORV;
OUTPUT:
	RETVAL

char *
sam_NAME()
CODE:
	RETVAL = SAM_NAME;
OUTPUT:
	RETVAL

char *
sam_SAM_VERSION()
CODE:
	RETVAL = SAM_VERSION;
OUTPUT:
	RETVAL

#ifdef SAM_BUILD_INFO

char *
sam_BUILD_INFO()
CODE:
        RETVAL = SAM_BUILD_INFO;
OUTPUT:
        RETVAL

#endif

#ifdef SAM_BUILD_UNAME
char *
sam_BUILD_UNAME()
CODE:
        RETVAL = SAM_BUILD_UNAME;
OUTPUT:
        RETVAL

#endif

#ifdef S_ISBLK

int
sam_S_ISBLK(mode)
	int	mode
CODE:
	RETVAL = S_ISBLK(mode);
OUTPUT:
	RETVAL

#endif

#ifdef S_ISCHR

int
sam_S_ISCHR(mode)
	int	mode
CODE:
	RETVAL = S_ISCHR(mode);
OUTPUT:
	RETVAL

#endif

#ifdef S_ISDIR

int
sam_S_ISDIR(mode)
	int	mode
CODE:
	RETVAL = S_ISDIR(mode);
OUTPUT:
	RETVAL

#endif

#ifdef S_ISFIFO

int
sam_S_ISFIFO(mode)
	int	mode
CODE:
	RETVAL = S_ISFIFO(mode);
OUTPUT:
	RETVAL

#endif

#ifdef S_ISGID

int
sam_S_ISGID(mode)
	int	mode
CODE:
	RETVAL = S_ISGID(mode);
OUTPUT:
	RETVAL

#endif

#ifdef S_ISREG

int
sam_S_ISREG(mode)
	int	mode
CODE:
	RETVAL = S_ISREG(mode);
OUTPUT:
	RETVAL

#endif

#ifdef S_ISUID

int
sam_S_ISUID(mode)
	int	mode
CODE:
	RETVAL = S_ISUID(mode);
OUTPUT:
	RETVAL

#endif

#ifdef S_ISLNK

int
sam_S_ISLNK(mode)
	int	mode
CODE:
	RETVAL = S_ISLNK(mode);
OUTPUT:
	RETVAL

#endif

#ifdef S_ISSOCK

int
sam_S_ISSOCK(mode)
	int	mode
CODE:
	RETVAL = S_ISSOCK(mode);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSAMFS

int
sam_SS_ISSAMFS(attr)
	int	attr
CODE:
	RETVAL = SS_ISSAMFS(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISREMEDIA

int
sam_SS_ISREMEDIA(attr)
	int	attr
CODE:
	RETVAL = SS_ISREMEDIA(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISARCHIVED

int
sam_SS_ISARCHIVED(attr)
	int	attr
CODE:
	RETVAL = SS_ISARCHIVED(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISARCHDONE

int
sam_SS_ISARCHDONE(attr)
	int	attr
CODE:
	RETVAL = SS_ISARCHDONE(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISDAMAGED

int
sam_SS_ISDAMAGED(attr)
	int	attr
CODE:
	RETVAL = SS_ISDAMAGED(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISOFFLINE

int
sam_SS_ISOFFLINE(attr)
	int	attr
CODE:
	RETVAL = SS_ISOFFLINE(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISPARTIAL

int
sam_SS_ISPARTIAL(attr)
	int	attr
CODE:
	RETVAL = SS_ISPARTIAL(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISARCHIVE_C

int
sam_SS_ISARCHIVE_C(attr)
	int	attr
CODE:
	RETVAL = SS_ISARCHIVE_C(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISARCHIVE_I

int
sam_SS_ISARCHIVE_I(attr)
	int	attr
CODE:
	RETVAL = SS_ISARCHIVE_I(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISARCHIVE_N

int
sam_SS_ISARCHIVE_N(attr)
	int	attr
CODE:
	RETVAL = SS_ISARCHIVE_N(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISARCHIVE_A

int
sam_SS_ISARCHIVE_A(attr)
	int	attr
CODE:
	RETVAL = SS_ISARCHIVE_A(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISARCHIVE_R

int
sam_SS_ISARCHIVE_R(attr)
	int	attr
CODE:
	RETVAL = SS_ISARCHIVE_R(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISRELEASE_A

int
sam_SS_ISRELEASE_A(attr)
	int	attr
CODE:
	RETVAL = SS_ISRELEASE_A(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISRELEASE_N

int
sam_SS_ISRELEASE_N(attr)
	int	attr
CODE:
	RETVAL = SS_ISRELEASE_N(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISRELEASE_P

int
sam_SS_ISRELEASE_P(attr)
	int	attr
CODE:
	RETVAL = SS_ISRELEASE_P(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSTAGE_A

int
sam_SS_ISSTAGE_A(attr)
	int	attr
CODE:
	RETVAL = SS_ISSTAGE_A(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSTAGE_N

int
sam_SS_ISSTAGE_N(attr)
	int	attr
CODE:
	RETVAL = SS_ISSTAGE_N(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSEGMENT_A

int
sam_SS_ISSEGMENT_A(attr)
	int	attr
CODE:
	RETVAL = SS_ISSEGMENT_A(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSEGMENT_S

int
sam_SS_ISSEGMENT_S(attr)
	int	attr
CODE:
	RETVAL = SS_ISSEGMENT_S(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSEGMENT_F

int
sam_SS_ISSEGMENT_F(attr)
	int	attr
CODE:
	RETVAL = SS_ISSEGMENT_F(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISCSGEN

int
sam_SS_ISCSGEN(attr)
	int	attr
CODE:
	RETVAL = SS_ISCSGEN(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISCSUSE

int
sam_SS_ISCSUSE(attr)
	int	attr
CODE:
	RETVAL = SS_ISCSUSE(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISCSVAL

int
sam_SS_ISCSVAL(attr)
	int	attr
CODE:
	RETVAL = SS_ISCSVAL(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISDIRECTIO

int
sam_SS_ISDIRECTIO(attr)
	int	attr
CODE:
	RETVAL = SS_ISDIRECTIO(attr);
OUTPUT:
	RETVAL

#endif

# Only SS_ISSTAGE_M is defined in stat.h, but SS_STAGE_M is missing.
# SamFS 4.6

#ifdef notdef

#ifdef SS_ISSTAGE_M

int
sam_SS_ISSTAGE_M(attr)
	int	attr
CODE:
	RETVAL = SS_ISSTAGE_M(attr);
OUTPUT:
	RETVAL

#endif

#endif

#ifdef SS_ISWORM

int
sam_SS_ISWORM(attr)
	int	attr
CODE:
	RETVAL = SS_ISWORM(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISREADONLY

int
sam_SS_ISREADONLY(attr)
	int	attr
CODE:
	RETVAL = SS_ISREADONLY(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSETFA_G

int
sam_SS_ISSETFA_G(attr)
	int	attr
CODE:
	RETVAL = SS_ISSETFA_G(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSETFA_S

int
sam_SS_ISSETFA_S(attr)
	int	attr
CODE:
	RETVAL = SS_ISSETFA_S(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISDFACL

int
sam_SS_ISDFACL(attr)
	int	attr
CODE:
	RETVAL = SS_ISDFACL(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISACL

int
sam_SS_ISACL(attr)
	int	attr
CODE:
	RETVAL = SS_ISACL(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISDATAV

int
sam_SS_ISDATAV(attr)
	int	attr
CODE:
	RETVAL = SS_ISDATAV(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISAIO

int
sam_SS_ISAIO(attr)
	int	attr
CODE:
	RETVAL = SS_ISAIO(attr);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSTAGING

int
sam_SS_ISSTAGING(flags)
	int	flags
CODE:
	RETVAL = SS_ISSTAGING(flags);
OUTPUT:
	RETVAL

#endif

#ifdef SS_ISSTAGEFAIL

int
sam_SS_ISSTAGEFAIL(flags)
	int	flags
CODE:
	RETVAL = SS_ISSTAGEFAIL(flags);
OUTPUT:
	RETVAL

#endif

int
sam_CS_NEEDS_AUDIT(status)
	int status;
CODE:
	RETVAL = (status & CSP_NEEDS_AUDIT) != 0;
OUTPUT:
	RETVAL

int
sam_CS_INUSE(status)
	int status;
CODE:
	RETVAL = (status & CSP_INUSE) != 0;
OUTPUT:
	RETVAL

int
sam_CS_LABELED(status)
	int status;
CODE:
	RETVAL = (status & CSP_LABELED) != 0;
OUTPUT:
	RETVAL

int
sam_CS_BADMEDIA(status)
	int status;
CODE:
	RETVAL = (status & CSP_BAD_MEDIA) != 0;
OUTPUT:
	RETVAL

int
sam_CS_OCCUPIED(status)
	int status;
CODE:
	RETVAL = (status & CSP_OCCUPIED) != 0;
OUTPUT:
	RETVAL

int
sam_CS_CLEANING(status)
	int status;
CODE:
	RETVAL = (status & CSP_CLEANING) != 0;
OUTPUT:
	RETVAL

int
sam_CS_BARCODE(status)
	int status;
CODE:
	RETVAL = (status & CSP_BAR_CODE) != 0;
OUTPUT:
	RETVAL

int
sam_CS_WRTPROT(status)
	int status;
CODE:
	RETVAL = (status & CSP_WRITEPROTECT) != 0;
OUTPUT:
	RETVAL

int
sam_CS_RDONLY(status)
	int status;
CODE:
	RETVAL = (status & CSP_READ_ONLY) != 0;
OUTPUT:
	RETVAL

int
sam_CS_RECYCLE(status)
	int status;
CODE:
	RETVAL = (status & CSP_RECYCLE) != 0;
OUTPUT:
	RETVAL

int
sam_CS_UNAVAIL(status)
	int status;
CODE:
	RETVAL = (status & CSP_UNAVAIL) != 0;
OUTPUT:
	RETVAL

int
sam_CS_EXPORT(status)
	int status;
CODE:
	RETVAL = (status & CSP_EXPORT) != 0;
OUTPUT:
	RETVAL

void
sam_stat(path)
	char *path
PREINIT:
	struct sam_stat statbuf;
	int retval;
	int i;
PPCODE:
	retval = sam_stat(path, &statbuf, sizeof statbuf);
	if (retval == 0) {
		EXTEND(SP, 22+MAX_ARCHIVE);
 /*  0 */	PUSHs(sv_2mortal(newSViv(statbuf.st_dev)));
 /*  1 */	PUSHs(sv_2mortal(newSViv(statbuf.st_ino)));
 /*  2 */	PUSHs(sv_2mortal(newSViv(statbuf.st_mode)));
 /*  3 */	PUSHs(sv_2mortal(newSViv(statbuf.st_nlink)));
 /*  4 */	PUSHs(sv_2mortal(newSViv(statbuf.st_uid)));
 /*  5 */	PUSHs(sv_2mortal(newSViv(statbuf.st_gid)));
 /*  6 */	PUSHs(sv_2mortal(newSViv(statbuf.rdev)));
 /*  7 */	PUSHs(sv_2mortal(newSVpv(ull2s(statbuf.st_size), 0)));
 /*  8 */	PUSHs(sv_2mortal(newSViv(statbuf.st_atime)));
 /*  9 */	PUSHs(sv_2mortal(newSViv(statbuf.st_mtime)));
 /* 10 */	PUSHs(sv_2mortal(newSViv(statbuf.st_ctime)));
 #ifdef OLD_SAMFS
 /* 11 */	PUSHs(&PL_sv_undef);    /* blksize */
 /* 12 */	PUSHs(&PL_sv_undef);    /* blocks */
 #else
 /* 11 */	PUSHs(sv_2mortal(newSViv(512)));	/* blksize */
 /* 12 */	PUSHs(sv_2mortal(newSVpv(ull2s(statbuf.st_blocks), 0)));
 #endif
 /* 13 */	PUSHs(sv_2mortal(newSViv(statbuf.attr)));
 /* 14 */	PUSHs(sv_2mortal(newSViv(statbuf.attribute_time)));
 /* 15 */	PUSHs(sv_2mortal(newSViv(statbuf.creation_time)));
 /* 16 */	PUSHs(sv_2mortal(newSViv(statbuf.residence_time)));
 /* 17 */	PUSHs(sv_2mortal(newSViv(statbuf.cs_algo)));
 /* 19 */	PUSHs(sv_2mortal(newSViv(statbuf.flags)));
 /* 20 */	PUSHs(sv_2mortal(newSViv(statbuf.gen)));
 /* 21 */	PUSHs(sv_2mortal(newSViv(statbuf.partial_size)));
		for (i=0; i<MAX_ARCHIVE; i++) {
			AV *av = newAV();
			av_extend(av, 7);
			PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
			av_store(av, 0, newSViv(statbuf.copy[i].flags));
			av_store(av, 1, newSViv(statbuf.copy[i].n_vsns));
			av_store(av, 2, newSViv(statbuf.copy[i].creation_time));
			av_store(av, 3, newSVpv(ull2s(statbuf.copy[i].position), 0));
			av_store(av, 4, newSViv(statbuf.copy[i].offset));
			av_store(av, 5, newSVpv(statbuf.copy[i].media, 0));
			av_store(av, 6, newSVpv(statbuf.copy[i].vsn, 0));
		}
	}

void
sam_lstat(path)
	char *path
PREINIT:
	struct sam_stat statbuf;
	int retval;
	int i;
PPCODE:
	retval = sam_lstat(path, &statbuf, sizeof statbuf);
	if (retval == 0) {
		EXTEND(SP, 22+MAX_ARCHIVE);
 /*  0 */	PUSHs(sv_2mortal(newSViv(statbuf.st_dev)));
 /*  1 */	PUSHs(sv_2mortal(newSViv(statbuf.st_ino)));
 /*  2 */	PUSHs(sv_2mortal(newSViv(statbuf.st_mode)));
 /*  3 */	PUSHs(sv_2mortal(newSViv(statbuf.st_nlink)));
 /*  4 */	PUSHs(sv_2mortal(newSViv(statbuf.st_uid)));
 /*  5 */	PUSHs(sv_2mortal(newSViv(statbuf.st_gid)));
 /*  6 */	PUSHs(sv_2mortal(newSViv(statbuf.rdev)));
 /*  7 */	PUSHs(sv_2mortal(newSVpv(ull2s(statbuf.st_size), 0)));
 /*  8 */	PUSHs(sv_2mortal(newSViv(statbuf.st_atime)));
 /*  9 */	PUSHs(sv_2mortal(newSViv(statbuf.st_mtime)));
 /* 10 */	PUSHs(sv_2mortal(newSViv(statbuf.st_ctime)));
 #ifdef OLD_SAMFS
 /* 11 */	PUSHs(&PL_sv_undef);    /* blksize */
 /* 12 */	PUSHs(&PL_sv_undef);    /* blocks */
 #else
 /* 11 */	PUSHs(sv_2mortal(newSViv(512)));	/* blksize */
 /* 12 */	PUSHs(sv_2mortal(newSVpv(ull2s(statbuf.st_blocks), 0)));
 #endif
 /* 13 */	PUSHs(sv_2mortal(newSViv(statbuf.attr)));
 /* 14 */	PUSHs(sv_2mortal(newSViv(statbuf.attribute_time)));
 /* 15 */	PUSHs(sv_2mortal(newSViv(statbuf.creation_time)));
 /* 16 */	PUSHs(sv_2mortal(newSViv(statbuf.residence_time)));
 /* 17 */	PUSHs(sv_2mortal(newSViv(statbuf.cs_algo)));
 /* 19 */	PUSHs(sv_2mortal(newSViv(statbuf.flags)));
 /* 20 */	PUSHs(sv_2mortal(newSViv(statbuf.gen)));
 /* 21 */	PUSHs(sv_2mortal(newSViv(statbuf.partial_size)));
		for (i=0; i<MAX_ARCHIVE; i++) {
			AV *av = newAV();
			av_extend(av, 7);
			PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
			av_store(av, 0, newSViv(statbuf.copy[i].flags));
			av_store(av, 1, newSViv(statbuf.copy[i].n_vsns));
			av_store(av, 2, newSViv(statbuf.copy[i].creation_time));
			av_store(av, 3, newSVpv(ull2s(statbuf.copy[i].position), 0));
			av_store(av, 4, newSViv(statbuf.copy[i].offset));
			av_store(av, 5, newSVpv(statbuf.copy[i].media, 0));
			av_store(av, 6, newSVpv(statbuf.copy[i].vsn, 0));
		}
	}

 /*
  * New versions. These return a reference to the array of copies
  * instead of the individual elements. They are also meant to be extended
  * when Sun introduces even more elements into the sam_stat struct.
 */

#ifndef OLD_SAMFS
void
sam_stat_scalars(path)
	char *path
PREINIT:
	struct sam_stat statbuf;
	int retval;
	int i;
        AV *copies;
PPCODE:
	retval = sam_stat(path, &statbuf, sizeof statbuf);
	if (retval == 0) {
		EXTEND(SP, 29);
 /*  0 */	PUSHs(sv_2mortal(newSViv(statbuf.st_dev)));
 /*  1 */	PUSHs(sv_2mortal(newSViv(statbuf.st_ino)));
 /*  2 */	PUSHs(sv_2mortal(newSViv(statbuf.st_mode)));
 /*  3 */	PUSHs(sv_2mortal(newSViv(statbuf.st_nlink)));
 /*  4 */	PUSHs(sv_2mortal(newSViv(statbuf.st_uid)));
 /*  5 */	PUSHs(sv_2mortal(newSViv(statbuf.st_gid)));
 /*  6 */	PUSHs(sv_2mortal(newSViv(statbuf.rdev)));
 /*  7 */	PUSHs(sv_2mortal(newSVpv(ull2s(statbuf.st_size), 0)));
 /*  8 */	PUSHs(sv_2mortal(newSViv(statbuf.st_atime)));
 /*  9 */	PUSHs(sv_2mortal(newSViv(statbuf.st_mtime)));
 /* 10 */	PUSHs(sv_2mortal(newSViv(statbuf.st_ctime)));
 /* 11 */	PUSHs(sv_2mortal(newSViv(512)));	/* blksize */
 /* 12 */	PUSHs(sv_2mortal(newSVpv(ull2s(statbuf.st_blocks), 0)));
 /* 13 */	PUSHs(sv_2mortal(newSViv(statbuf.attr)));
 /* 14 */	PUSHs(sv_2mortal(newSViv(statbuf.attribute_time)));
 /* 15 */	PUSHs(sv_2mortal(newSViv(statbuf.creation_time)));
 /* 16 */	PUSHs(sv_2mortal(newSViv(statbuf.residence_time)));
 /* 17 */	PUSHs(sv_2mortal(newSViv(statbuf.cs_algo)));
 /* 18 */	PUSHs(sv_2mortal(newSViv(statbuf.flags)));
 /* 19 */	PUSHs(sv_2mortal(newSViv(statbuf.gen)));
 /* 20 */	PUSHs(sv_2mortal(newSViv(statbuf.partial_size)));
                copies = newAV();
                sv_2mortal((SV*)copies);
                av_extend(copies, MAX_ARCHIVE);
 /* 21 */	PUSHs(sv_2mortal(newRV_noinc((SV*)copies)));
		for (i=0; i<MAX_ARCHIVE; i++) {
			AV *av = newAV();
                        av_store(copies, i, newRV_noinc((SV*)av));
			av_extend(av, 7);
			av_store(av, 0, newSViv(statbuf.copy[i].flags));
			av_store(av, 1, newSViv(statbuf.copy[i].n_vsns));
			av_store(av, 2, newSViv(statbuf.copy[i].creation_time));
			av_store(av, 3, newSVpv(ull2s(statbuf.copy[i].position), 0));
			av_store(av, 4, newSViv(statbuf.copy[i].offset));
			av_store(av, 5, newSVpv(statbuf.copy[i].media, 0));
			av_store(av, 6, newSVpv(statbuf.copy[i].vsn, 0));
		}
 /* 22 */	PUSHs(sv_2mortal(newSViv(statbuf.stripe_width)));
 /* 23 */	PUSHs(sv_2mortal(newSViv(statbuf.stripe_group)));
 /* 24 */	PUSHs(sv_2mortal(newSViv(statbuf.segment_size)));
 /* 25 */	PUSHs(sv_2mortal(newSViv(statbuf.segment_number)));
 /* 26 */	PUSHs(sv_2mortal(newSViv(statbuf.stage_ahead)));
 /* 27 */	PUSHs(sv_2mortal(newSViv(statbuf.admin_id)));
 /* 28 */	PUSHs(sv_2mortal(newSViv(statbuf.allocahead)));
	}

void
sam_lstat_scalars(path)
	char *path
PREINIT:
	struct sam_stat statbuf;
	int retval;
	int i;
        AV *copies;
PPCODE:
	retval = sam_lstat(path, &statbuf, sizeof statbuf);
	if (retval == 0) {
		EXTEND(SP, 29);
 /*  0 */	PUSHs(sv_2mortal(newSViv(statbuf.st_dev)));
 /*  1 */	PUSHs(sv_2mortal(newSViv(statbuf.st_ino)));
 /*  2 */	PUSHs(sv_2mortal(newSViv(statbuf.st_mode)));
 /*  3 */	PUSHs(sv_2mortal(newSViv(statbuf.st_nlink)));
 /*  4 */	PUSHs(sv_2mortal(newSViv(statbuf.st_uid)));
 /*  5 */	PUSHs(sv_2mortal(newSViv(statbuf.st_gid)));
 /*  6 */	PUSHs(sv_2mortal(newSViv(statbuf.rdev)));
 /*  7 */	PUSHs(sv_2mortal(newSVpv(ull2s(statbuf.st_size), 0)));
 /*  8 */	PUSHs(sv_2mortal(newSViv(statbuf.st_atime)));
 /*  9 */	PUSHs(sv_2mortal(newSViv(statbuf.st_mtime)));
 /* 10 */	PUSHs(sv_2mortal(newSViv(statbuf.st_ctime)));
 /* 11 */	PUSHs(sv_2mortal(newSViv(512)));	/* blksize */
 /* 12 */	PUSHs(sv_2mortal(newSVpv(ull2s(statbuf.st_blocks), 0)));
 /* 13 */	PUSHs(sv_2mortal(newSViv(statbuf.attr)));
 /* 14 */	PUSHs(sv_2mortal(newSViv(statbuf.attribute_time)));
 /* 15 */	PUSHs(sv_2mortal(newSViv(statbuf.creation_time)));
 /* 16 */	PUSHs(sv_2mortal(newSViv(statbuf.residence_time)));
 /* 17 */	PUSHs(sv_2mortal(newSViv(statbuf.cs_algo)));
 /* 18 */	PUSHs(sv_2mortal(newSViv(statbuf.flags)));
 /* 19 */	PUSHs(sv_2mortal(newSViv(statbuf.gen)));
 /* 20 */	PUSHs(sv_2mortal(newSViv(statbuf.partial_size)));
                copies = newAV();
                sv_2mortal((SV*)copies);
                av_extend(copies, MAX_ARCHIVE);
 /* 21 */	PUSHs(sv_2mortal(newRV_noinc((SV*)copies)));
		for (i=0; i<MAX_ARCHIVE; i++) {
			AV *av = newAV();
                        av_store(copies, i, newRV_noinc((SV*)av));
			av_extend(av, 7);
			av_store(av, 0, newSViv(statbuf.copy[i].flags));
			av_store(av, 1, newSViv(statbuf.copy[i].n_vsns));
			av_store(av, 2, newSViv(statbuf.copy[i].creation_time));
			av_store(av, 3, newSVpv(ull2s(statbuf.copy[i].position), 0));
			av_store(av, 4, newSViv(statbuf.copy[i].offset));
			av_store(av, 5, newSVpv(statbuf.copy[i].media, 0));
			av_store(av, 6, newSVpv(statbuf.copy[i].vsn, 0));
		}
 /* 22 */	PUSHs(sv_2mortal(newSViv(statbuf.stripe_width)));
 /* 23 */	PUSHs(sv_2mortal(newSViv(statbuf.stripe_group)));
 /* 24 */	PUSHs(sv_2mortal(newSViv(statbuf.segment_size)));
 /* 25 */	PUSHs(sv_2mortal(newSViv(statbuf.segment_number)));
 /* 26 */	PUSHs(sv_2mortal(newSViv(statbuf.stage_ahead)));
 /* 27 */	PUSHs(sv_2mortal(newSViv(statbuf.admin_id)));
 /* 28 */	PUSHs(sv_2mortal(newSViv(statbuf.allocahead)));
	}

#endif

#ifdef OLD_SAMFS

void
sam_vsn_stat(path, copy)
	char *	path
	int	copy
PREINIT:
#ifndef MAX_VSNS
 /* Make SamFS 3.3.1-15 backwards compatible */
#define MAX_VSNS MAX_VOLUMES
	struct sam_vsn_stat {
		struct sam_section section[MAX_VOLUMES];
	};
#define CAST (struct sam_section*)
#else
#define CAST
#endif
	struct sam_vsn_stat statbuf;
	int retval;
	int i;
PPCODE:
	retval = sam_vsn_stat(path, copy, CAST &statbuf, sizeof statbuf);
	if (retval == 0) {
		EXTEND(SP, MAX_VSNS);
		for (i=0; i<MAX_VSNS; i++) {
			AV *av = newAV();
			av_extend(av, 4);
			PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
			av_store(av, 0, newSVpv(statbuf.section[i].vsn, 0));
			av_store(av, 1, newSVpv(ull2s(statbuf.section[i].length), 0));
			av_store(av, 2, newSVpv(ull2s(statbuf.section[i].position), 0));
			av_store(av, 3, newSVpv(ull2s(statbuf.section[i].offset), 0));
		}
	}

#else

void
sam_vsn_stat(path, copy)
	char *	path
	int	copy
PREINIT:
	struct sam_section statbuf;
	int retval;
	int i;
PPCODE:
	retval = sam_vsn_stat(path, copy, &statbuf, sizeof statbuf);
	if (retval == 0) {
		EXTEND(SP, 1);
		AV *av = newAV();
		av_extend(av, 4);
		PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
		av_store(av, 0, newSVpv(statbuf.vsn, 0));
		av_store(av, 1, newSVpv(ull2s(statbuf.length), 0));
		av_store(av, 2, newSVpv(ull2s(statbuf.position), 0));
		av_store(av, 3, newSVpv(ull2s(statbuf.offset), 0));
	}

#endif

# The sam_segment_foo and sam_restore_foo functions have been
# introduced after I was cut off from any running SamFS
# installation. This code should be conditional on *something* to be
# compatible with old SamFS versions that don't have the functions. But
# conditional on *what*?!? So for now they are just wrapped in an
# #ifndef OLD_SAMFS.
# Because I have no way of testing this, the code will probably
# contain mistakes because of my misunderstandings of the terse
# documentation.

#ifndef OLD_SAMFS
int
sam_segment_vsn_stat(path, copy, segment_index)
	char *			path
	int			copy
	int			segment_index
PREINIT:
	struct sam_section statbuf;
	int retval;
	int i;
PPCODE:
	retval = sam_segment_vsn_stat(path, copy, segment_index, &statbuf, sizeof statbuf);
	if (retval == 0) {
		EXTEND(SP, 1);
		AV *av = newAV();
		av_extend(av, 4);
		PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
		av_store(av, 0, newSVpv(statbuf.vsn, 0));
		av_store(av, 1, newSVpv(ull2s(statbuf.length), 0));
		av_store(av, 2, newSVpv(ull2s(statbuf.position), 0));
		av_store(av, 3, newSVpv(ull2s(statbuf.offset), 0));
	}

int
sam_segment_stat(path)
	char *			path
PREINIT:
	struct sam_stat file_info;
	struct sam_stat *data_seg_info_ptr;
	int number_of_data_segments;
	int retval;
	int i;
PPCODE:
	retval = sam_stat(path, &file_info, sizeof file_info);
	if (retval == 0) {
		if (SS_ISSEGMENT_F(file_info.attr)) {
	                number_of_data_segments = NUM_SEGS(&file_info);
                        Newxz(data_seg_info_ptr, number_of_data_segments,
                              struct sam_stat);
                	retval = sam_segment_stat(path, data_seg_info_ptr,
                                                  number_of_data_segments *
                                                  sizeof(struct sam_stat));
                        if (retval == 0) {
                		EXTEND(SP, number_of_data_segments);
                                for (i=0; i<number_of_data_segments; i++) {
                                        AV *av;
                                        av = newAV();
                                        sv_2mortal((SV*)av);
                                        av_extend(av, 30);
                                        PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
                                        sam_stat2av(&file_info, av);
                                }
                        }
	                Safefree(data_seg_info_ptr);
                } else {
                        /* Not segmented, just return a list of one element,
                           from file_info. */
                        AV *av;
        		EXTEND(SP, 1);
                        av = newAV();
                        sv_2mortal((SV*)av);
                        av_extend(av, 30);
                        PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
                        sam_stat2av(&file_info, av);
                }
        }

int
sam_segment_lstat(path)
	char *			path
PREINIT:
	struct sam_stat file_info;
	struct sam_stat *data_seg_info_ptr;
	int number_of_data_segments;
	int retval;
	int i;
PPCODE:
	retval = sam_lstat(path, &file_info, sizeof file_info);
	if (retval == 0) {
		if (SS_ISSEGMENT_F(file_info.attr)) {
	                number_of_data_segments = NUM_SEGS(&file_info);
                        Newxz(data_seg_info_ptr, number_of_data_segments,
                              struct sam_stat);
                	retval = sam_segment_lstat(path, data_seg_info_ptr,
                                                  number_of_data_segments *
                                                  sizeof(struct sam_stat));
                        if (retval == 0) {
                		EXTEND(SP, number_of_data_segments);
                                for (i=0; i<number_of_data_segments; i++) {
                                        AV *av;
                                        av = newAV();
                                        sv_2mortal((SV*)av);
                                        av_extend(av, 30);
                                        PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
                                        sam_stat2av(&file_info, av);
                                }
                        }
	                Safefree(data_seg_info_ptr);
                } else {
                        /* Not segmented, just return a list of one element,
                           from file_info. */
                        AV *av;
        		EXTEND(SP, 1);
                        av = newAV();
                        sv_2mortal((SV*)av);
                        av_extend(av, 30);
                        PUSHs(sv_2mortal(newRV_noinc((SV*)av)));
                        sam_stat2av(&file_info, av);
                }
        }

int
sam_restore_file(path, st_mode, st_uid, st_gid, st_size, st_atime, st_ctime, st_mtime, copies)
	char *          path
	unsigned long	st_mode
	unsigned long	st_uid
	unsigned long	st_gid
	char *          st_size
	unsigned long	st_atime
	unsigned long	st_ctime
	unsigned long	st_mtime
        SV *            copies
INIT:
	struct sam_stat info;
        int i;
CODE:
        if ((!SvROK(copies)) || (SvTYPE(SvRV(copies)) != SVt_PVAV)) {
                croak("\"copies\" argument has wrong type - must be array ref");
        } else if (av_len((AV*)copies) != MAX_ARCHIVE) {
                croak("\"copies\" argument must have exactly %d elements",
                      MAX_ARCHIVE);
        }
        info.st_mode = st_mode;
        info.st_uid = st_uid;
        info.st_gid = st_gid;
        sscanf(st_size, "%llu", &info.st_size);
        info.st_atime = st_atime;
        info.st_ctime = st_ctime;
        info.st_mtime = st_mtime;
        for (i=0; i<MAX_ARCHIVE; i++) {
                AV *copy;
                STRLEN l;
                char *media;
                char *vsn;
                copy = (AV*)*av_fetch((AV*)SvRV(copies), i, 0);
                media = SvPV(*av_fetch(copy, 0, 0), l);
                if (l > 4) {
                        l = 4;
                }
                strncpy(info.copy[i].media, media, l);
                sscanf(SvPV_nolen(*av_fetch(copy, 1, 0)), "%llu",
                       &info.copy[i].position);
                info.copy[i].creation_time =
                        (time_t)SvIV(*av_fetch(copy, 2, 0));
                vsn = SvPV(*av_fetch(copy, 3, 0), l);
                if (l > 32) {
                        l = 32;
                }
                strncpy(info.copy[i].vsn, vsn, l);
        }
        RETVAL = sam_restore_file(path, &info, sizeof info);
OUTPUT:
        RETVAL

int
sam_restore_copy(path, copy_no, st_mode, st_uid, st_gid, st_size, st_atime, st_ctime, st_mtime, copy_info, ...)
	char *		path
	int		copy_no
	unsigned long	st_mode
	unsigned long	st_uid
	unsigned long	st_gid
	char *          st_size
	unsigned long	st_atime
	unsigned long	st_ctime
	unsigned long	st_mtime
        SV *            copy_info
INIT:
	struct sam_stat info;
        struct sam_section *sinfo;
        int sinfosize;
        AV *av;
        int l;
        char *media;
        char *vsn;
        int i;

        if ((!SvROK(copy_info)) || (SvTYPE(SvRV(copy_info)) != SVt_PVAV)) {
                croak("\"copy_info\" argument has wrong type - must be array ref");
        } else if (av_len((AV *)SvRV(copy_info)) != 5) {
                croak("\"copy_info\" argument must have exactly 5 elements");
        }
CODE:
        info.st_mode = st_mode;
        info.st_uid = st_uid;
        info.st_gid = st_gid;
        sscanf(st_size, "%llu", &info.st_size);
        info.st_atime = st_atime;
        info.st_ctime = st_ctime;
        info.st_mtime = st_mtime;
	av = (AV*)SvRV(copy_info);
	media = SvPV(*av_fetch(av, 0, 0), l);
	if (l > 4) {
	        l = 4;
	}
	strncpy(info.copy[copy_no].media, media, l);
	sscanf(SvPV_nolen(*av_fetch(av, 1, 0)), "%llu",
	       &info.copy[copy_no].position);
	info.copy[copy_no].creation_time =
	        (time_t)SvIV(*av_fetch(av, 2, 0));
	vsn = SvPV(*av_fetch(av, 3, 0), l);
	if (l > 32) {
	        l = 32;
	}
	strncpy(info.copy[copy_no].vsn, vsn, l);
        info.copy[copy_no].offset = SvIV(*av_fetch(av, 2, 0));
        /* info.copy[copy_no].vsns is implicitly defined by the number
           of sections supplied */
        info.copy[copy_no].n_vsns = 1;
        sinfo = (struct sam_section *)0;
        sinfosize = 0;
        if (items > 9) {
                /* sections array, check it */
                SV *sv = ST(9);
                if ((!SvROK(sv)) || (SvTYPE(SvRV(sv)) != SVt_PVAV)) {
                       croak("\"sections\" has wrong type - must be array ref");
                }
                av = (AV*)sv;
                info.copy[copy_no].n_vsns = av_len(av) + 1;
                Newxz(sinfo, av_len(av), struct sam_section);
                sinfosize = av_len(av) * sizeof(struct sam_section);
                for (i=0; i<av_len(av); i++) {
                        AV *av2;
                        char *vsn;
                        av2 = (AV*)*av_fetch((AV*)SvRV(av), i, 0);
                        if ((!SvROK(av2)) || (SvTYPE(SvRV(av2)) != SVt_PVAV)) {
                                croak("section %d has wrong type - must be array ref",
                                      i);
                        } else if (av_len((AV *)SvRV(copy_info)) != 4) {
                                croak("section must have exactly 4 elements");
                        }
                        vsn = SvPV(*av_fetch(av2, 0, 0), l);
                        if (l > 32) {
                                l = 32;
                        }
                        strncpy(sinfo[i].vsn, vsn, l);
                        sscanf(SvPV_nolen(*av_fetch(av2, 1, 0)), "%llu",
                               &sinfo[i].length);
                        sscanf(SvPV_nolen(*av_fetch(av2, 2, 0)), "%llu",
                               &sinfo[i].position);
                        sscanf(SvPV_nolen(*av_fetch(av2, 3, 0)), "%llu",
                               &sinfo[i].offset);
                }
        }

        RETVAL = sam_restore_copy(path, copy_no,
                                  &info, sizeof info,
                                  sinfo, sinfosize);
OUTPUT:
        RETVAL

#endif

char *
sam_attrtoa(attr)
	int	attr
CODE:
	RETVAL = sam_attrtoa(attr, NULL);
OUTPUT:
	RETVAL

void
sam_devstat(eq)
	int	eq
PREINIT:
	struct sam_devstat statbuf;
	int retval;
PPCODE:
	retval = sam_devstat(eq, &statbuf, sizeof statbuf);
	if (retval == 0) {
		EXTEND(SP, 7);
/* 0 */		PUSHs(sv_2mortal(newSViv(statbuf.type)));
/* 1 */		PUSHs(sv_2mortal(newSVpv(statbuf.name, 0)));
/* 2 */		PUSHs(sv_2mortal(newSVpv(statbuf.vsn, 0)));
/* 3 */		PUSHs(sv_2mortal(newSVpv(dev_state[statbuf.state], 0)));
/* 4 */		PUSHs(sv_2mortal(newSViv(statbuf.status)));
/* 5 */		PUSHs(sv_2mortal(newSViv(statbuf.space)));
/* 6 */		PUSHs(sv_2mortal(newSViv(statbuf.capacity)));
	}

void
sam_ndevstat(eq)
	int	eq
PREINIT:
	struct sam_ndevstat statbuf;
	int retval;
PPCODE:
	retval = sam_ndevstat(eq, &statbuf, sizeof statbuf);
	if (retval == 0) {
		EXTEND(SP, 7);
/* 0 */		PUSHs(sv_2mortal(newSViv(statbuf.type)));
/* 1 */		PUSHs(sv_2mortal(newSVpv(statbuf.name, 0)));
/* 2 */		PUSHs(sv_2mortal(newSVpv(statbuf.vsn, 0)));
/* 3 */		PUSHs(sv_2mortal(newSVpv(dev_state[statbuf.state], 0)));
/* 4 */		PUSHs(sv_2mortal(newSViv(statbuf.status)));
/* 5 */		PUSHs(sv_2mortal(newSViv(statbuf.space)));
/* 6 */		PUSHs(sv_2mortal(newSViv(statbuf.capacity)));
	}

char *
sam_devstr(status)
	int	status
CODE:
	RETVAL = sam_devstr(status);
OUTPUT:
	RETVAL

void
sam_opencat(path)
	char *	path
PREINIT:
	struct sam_cat_tbl catbuf;
	int retval;
PPCODE:
	retval = sam_opencat(path, &catbuf, sizeof catbuf);
	if (retval >= 0) {
		EXTEND(SP, 4);
/* 0 */		PUSHs(sv_2mortal(newSViv(retval)));
/* 1 */		PUSHs(sv_2mortal(newSViv(catbuf.audit_time)));
/* 2 */		PUSHs(sv_2mortal(newSViv(catbuf.version)));
/* 3 */		PUSHs(sv_2mortal(newSViv(catbuf.count)));
/* 4 */		PUSHs(sv_2mortal(newSVpv(catbuf.media, 0)));
	}

int
sam_closecat(cat_handle)
	int	cat_handle

void
sam_getcatalog(cat_handle, slot)
	int	cat_handle
	int	slot
PREINIT:
	struct sam_cat_ent	catbuf;
	int retval;
PPCODE:
	retval = sam_getcatalog(cat_handle, slot, slot, &catbuf, sizeof catbuf);
	if (retval >= 0) {
		EXTEND(SP, 11);
/* 0 */		PUSHs(sv_2mortal(newSViv(catbuf.type)));
/* 1 */		PUSHs(sv_2mortal(newSViv(catbuf.status)));
/* 2 */		PUSHs(sv_2mortal(newSVpv(catbuf.media, 0)));
/* 3 */		PUSHs(sv_2mortal(newSVpv(catbuf.vsn, 0)));
/* 4 */		PUSHs(sv_2mortal(newSViv(catbuf.access)));
/* 5 */		PUSHs(sv_2mortal(newSViv(catbuf.capacity)));
/* 6 */		PUSHs(sv_2mortal(newSViv(catbuf.space)));
/* 7 */		PUSHs(sv_2mortal(newSViv(catbuf.ptoc_fwa)));
/* 8 */		PUSHs(sv_2mortal(newSViv(catbuf.modification_time)));
/* 9 */		PUSHs(sv_2mortal(newSViv(catbuf.mount_time)));
/*10 */		PUSHs(sv_2mortal(newSVpv(catbuf.bar_code, 0)));
	}


int
sam_archive(name, opns)
	char *	name
	char *	opns

int
sam_cancelstage(name)
	char *	name

int
sam_release(name, opns)
	char *	name
	char *	opns

int
sam_ssum(name, opns)
	char *	name
	char *	opns

int
sam_stage(name, opns)
	char *	name
	char *	opns

int
sam_setfa(name, opns)
	char *	name
	char *	opns

int
sam_advise(fildes, opns)
	int	fildes
	char *	opns

# Not yet implemented.

#-# int
#-# sam_request(path, buf, bufsize)
#-# 	char *			path
#-# 	struct sam_rminfo *	buf
#-# 	size_t			bufsize

# Not documented
#-# int
#-# sam_readrminfo(path, buf, bufsize)
#-# 	char *	path
#-# 	struct sam_rminfo *	buf
#-# 	size_t	bufsize

#-# int
#-# sam_segment(name, opns);
#-# 	char *	name
#-# 	char *	opns

# is_<foo> macros from devstat.h

#ifdef is_disk

int
sam_is_disk(a)
	int	a
CODE:
	RETVAL = is_disk(a);
OUTPUT:
	RETVAL

#endif

#ifdef is_optical

int
sam_is_optical(a)
	int	a
CODE:
	RETVAL = is_optical(a);
OUTPUT:
	RETVAL

#endif

#ifdef is_robot

int
sam_is_robot(a)
	int	a
CODE:
	RETVAL = is_robot(a);
OUTPUT:
	RETVAL

#endif

#ifdef is_tape

int
sam_is_tape(a)
	int	a
CODE:
	RETVAL = is_tape(a);
OUTPUT:
	RETVAL

#endif

#ifdef is_tapelib

int
sam_is_tapelib(a)
	int	a
CODE:
	RETVAL = is_tapelib(a);
OUTPUT:
	RETVAL

#endif

#ifdef is_third_party

int
sam_is_third_party(a)
	int	a
CODE:
	RETVAL = is_third_party(a);
OUTPUT:
	RETVAL

#endif

#ifdef is_stripe_group

int
sam_is_stripe_group(a)
	int	a
CODE:
	RETVAL = is_stripe_group(a);
OUTPUT:
	RETVAL

#endif

#ifdef is_rsd

int
sam_is_rsd(a)
	int	a
CODE:
	RETVAL = is_rsd(a);
OUTPUT:
	RETVAL

#endif

#ifdef is_stk

int
sam_is_stk5800(a)
	int	a
CODE:
	RETVAL = is_stk5800(a);
OUTPUT:
	RETVAL

#endif