[OpenAFS] check in c (linux) whether a directory entry is a
mount point for an AFS volume
Michael Meffie
mmeffie@sinenomine.net
Fri, 3 Aug 2018 23:04:44 -0400
On Fri, 3 Aug 2018 13:22:05 +0200
Stephan Wiesand <stephan.wiesand@desy.de> wrote:
>
> > On 3. Aug 2018, at 13:08, Christian <chanlists@googlemail.com> wrote:
>
> > is there an easy way to check in C (under linux) whether a directory
> > entry is a mount point for an afs volume and maybe also obtain the name
> > of the volume mounted?
>
> popen("fs lsm /the/path", "r") ?
Hi Christian,
Since you asked for a way to check in C, looking at the fs lsmount
implementation, you can see the OpenAFS fs program issues an ioctl (under linux) to
do a "mount point stat". The ioctl returns EINVAL if the path is not an openafs
"mount point".
Here's a working example (for linux only):
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#define AFSCALL_PIOCTL 20
#define AFS_PIOCTL_MAXSIZE 2048
#define _VICEIOCTL(id) ((unsigned int) _IOW('V', id, struct ViceIoctl))
#define VIOC_AFS_STAT_MT_PT _VICEIOCTL(29)
#define VIOC_SYSCALL_TYPE 'C'
#define VIOC_SYSCALL _IOW(VIOC_SYSCALL_TYPE,1,void *)
#define PROC_SYSCALL_FNAME "/proc/fs/openafs/afs_ioctl"
struct ViceIoctl {
caddr_t in;
caddr_t out;
short in_size;
short out_size;
};
struct afsprocdata {
long param4;
long param3;
long param2;
long param1;
long syscall;
};
char buffer[AFS_PIOCTL_MAXSIZE];
int pioctl(char *path, int command, struct ViceIoctl *arg, int follow)
{
int code;
int fd;
struct afsprocdata syscall_data;
fd = open(PROC_SYSCALL_FNAME, O_RDONLY);
if (fd < 0) {
fprintf(stderr, "failed to open %s; errno=%d\n", PROC_SYSCALL_FNAME, errno);
return -1;
}
syscall_data.syscall = (long)AFSCALL_PIOCTL;
syscall_data.param1 = (long)path;
syscall_data.param2 = (long)command;
syscall_data.param3 = (long)arg;
syscall_data.param4 = (long)follow;
code = ioctl(fd, VIOC_SYSCALL, &syscall_data);
close(fd);
return code;
}
int main(int argc, char *argv)
{
int code;
struct ViceIoctl blob;
char *parent = "/afs/example.com/test";
char *last = "xyzzy";
memset(buffer, 0, AFS_PIOCTL_MAXSIZE);
blob.in = last;
blob.in_size = strlen(last) + 1;
blob.out_size = AFS_PIOCTL_MAXSIZE;
blob.out = buffer;
code = pioctl(parent, VIOC_AFS_STAT_MT_PT, &blob, 1);
if (code == 0) {
printf("%s/%s is a mount point for volume %s\n", parent, last, buffer);
} else if (errno == EINVAL) {
printf("%s/%s is not a mount point\n", parent, last);
} else {
fprintf(stderr, "pioctl failed: code=%d; errno=%d\n", code, errno);
}
return 0;
}
/*
* Example usage:
*
* $ make lsm
* cc lsm.c -o lsm
* $ ./lsm
* /afs/example.com/test/xyzzy is a mount point for volume #xyzzy
*
*/
Hope this helps,
Mike
--
Michael Meffie <mmeffie@sinenomine.net>