mirror of
https://github.com/ibm-s390-linux/s390-tools.git
synced 2026-08-05 02:14:52 +00:00
This commit is based on the s390-tools-1.39.0 version. Changes on top of s390-tools-1.39.0: - Add MIT license to all source files - Add LICENSE file - Transform REAMDE to README.md (markdown) - Add AUTHORS.md file - Add CONTRIBUTING.md file - Move changelog from README to CHANGELOG.md file Reviewed-by: Stefan Haberland <sth@linux.vnet.ibm.com> Signed-off-by: Michael Holzheu <holzheu@linux.vnet.ibm.com>
242 lines
5.0 KiB
C
242 lines
5.0 KiB
C
/*
|
|
* zgetdump - Tool for copying and converting System z dumps
|
|
*
|
|
* FUSE functions
|
|
*
|
|
* Copyright IBM Corp. 2010, 2017
|
|
*
|
|
* s390-tools is free software; you can redistribute it and/or modify
|
|
* it under the terms of the MIT license. See LICENSE for details.
|
|
*/
|
|
|
|
#define FUSE_USE_VERSION 25
|
|
|
|
#include <errno.h>
|
|
#include <fcntl.h>
|
|
#include <fuse.h>
|
|
#include <limits.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/stat.h>
|
|
#include <sys/types.h>
|
|
#include <time.h>
|
|
#include <unistd.h>
|
|
|
|
#include "zgetdump.h"
|
|
|
|
#define DUMP_PATH_MAX 100
|
|
|
|
/*
|
|
* File local static data
|
|
*/
|
|
static struct {
|
|
char path[DUMP_PATH_MAX];
|
|
struct stat stat_root;
|
|
struct stat stat_dump;
|
|
} l;
|
|
|
|
/*
|
|
* Initialize default values for stat buffer
|
|
*/
|
|
static void stat_default_init(struct stat *stat)
|
|
{
|
|
if (dfi_attr_time()) {
|
|
stat->st_mtime = dfi_attr_time()->tv_sec;
|
|
stat->st_ctime = dfi_attr_time()->tv_sec;
|
|
stat->st_atime = dfi_attr_time()->tv_sec;
|
|
} else {
|
|
stat->st_mtime = zg_stat(g.fh)->st_mtime;
|
|
stat->st_ctime = zg_stat(g.fh)->st_ctime;
|
|
stat->st_atime = zg_stat(g.fh)->st_atime;
|
|
}
|
|
stat->st_uid = geteuid();
|
|
stat->st_gid = getegid();
|
|
}
|
|
|
|
/*
|
|
* Initialize stat buffer for root directory
|
|
*/
|
|
static void stat_root_init(void)
|
|
{
|
|
stat_default_init(&l.stat_root);
|
|
l.stat_root.st_mode = S_IFDIR | 0500;
|
|
l.stat_root.st_nlink = 2;
|
|
}
|
|
|
|
/*
|
|
* Initialize stat buffer for dump
|
|
*/
|
|
static void stat_dump_init(void)
|
|
{
|
|
stat_default_init(&l.stat_dump);
|
|
l.stat_dump.st_mode = S_IFREG | 0400;
|
|
l.stat_dump.st_nlink = 1;
|
|
l.stat_dump.st_size = dfo_size();
|
|
l.stat_dump.st_blksize = 4096;
|
|
l.stat_dump.st_blocks = l.stat_dump.st_size / 4096;
|
|
}
|
|
|
|
/*
|
|
* FUSE callback: Getattr
|
|
*/
|
|
static int zfuse_getattr(const char *path, struct stat *stat)
|
|
{
|
|
if (strcmp(path, "/") == 0) {
|
|
*stat = l.stat_root;
|
|
return 0;
|
|
}
|
|
if (strcmp(path, l.path) == 0) {
|
|
*stat = l.stat_dump;
|
|
return 0;
|
|
}
|
|
return -ENOENT;
|
|
}
|
|
|
|
/*
|
|
* FUSE callback: Readdir - Return ".", ".." and dump file
|
|
*/
|
|
static int zfuse_readdir(const char *path, void *buf, fuse_fill_dir_t filler,
|
|
off_t offset, struct fuse_file_info *fi)
|
|
{
|
|
(void) offset;
|
|
(void) fi;
|
|
|
|
if (strcmp(path, "/") != 0)
|
|
return -ENOENT;
|
|
|
|
filler(buf, ".", NULL, 0);
|
|
filler(buf, "..", NULL, 0);
|
|
filler(buf, &l.path[1], NULL, 0);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* FUSE callback: Open
|
|
*/
|
|
static int zfuse_open(const char *path, struct fuse_file_info *fi)
|
|
{
|
|
if (strcmp(path, l.path) != 0)
|
|
return -ENOENT;
|
|
if ((fi->flags & 3) != O_RDONLY)
|
|
return -EACCES;
|
|
l.stat_dump.st_atime = time(NULL);
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* FUSE callback: Read
|
|
*/
|
|
static int zfuse_read(const char *path, char *buf, size_t size, off_t offset,
|
|
struct fuse_file_info *fi)
|
|
{
|
|
(void) fi;
|
|
|
|
if (strcmp(path, l.path) != 0)
|
|
return -ENOENT;
|
|
dfo_seek(offset);
|
|
dfo_read(buf, size);
|
|
return size;
|
|
}
|
|
|
|
/*
|
|
* FUSE callback: Statfs
|
|
*/
|
|
static int zfuse_statfs(const char *path, struct statvfs *buf)
|
|
{
|
|
(void) path;
|
|
|
|
buf->f_bsize = buf->f_frsize = 4096;
|
|
buf->f_blocks = dfo_size() / 4096;
|
|
buf->f_bfree = buf->f_bavail = 0;
|
|
buf->f_files = 1;
|
|
buf->f_ffree = 0;
|
|
buf->f_namemax = strlen(l.path) + 1;
|
|
return 0;
|
|
}
|
|
|
|
/*
|
|
* FUSE operations
|
|
*/
|
|
static struct fuse_operations zfuse_ops = {
|
|
.getattr = zfuse_getattr,
|
|
.readdir = zfuse_readdir,
|
|
.open = zfuse_open,
|
|
.read = zfuse_read,
|
|
.statfs = zfuse_statfs,
|
|
};
|
|
|
|
/*
|
|
* Add additional FUSE arguments
|
|
*/
|
|
static void add_argv_fuse(struct fuse_args *args)
|
|
{
|
|
int i;
|
|
|
|
if (g.opts.argc_fuse == 0)
|
|
return;
|
|
STDERR("Adding Fuse options: ");
|
|
for (i = 0; i < g.opts.argc_fuse; i++) {
|
|
STDERR("%s ", g.opts.argv_fuse[i]);
|
|
fuse_opt_add_arg(args, g.opts.argv_fuse[i]);
|
|
}
|
|
STDERR("\n");
|
|
}
|
|
|
|
/*
|
|
* Mount dump
|
|
*
|
|
* Add additional FUSE options:
|
|
* - s....................: Disable multi-threaded operation
|
|
* - o fsname.............: File system name (used for umount)
|
|
* - o ro.................: Read only
|
|
* - o default_permissions: Enable permission checking by kernel
|
|
*/
|
|
int zfuse_mount_dump(void)
|
|
{
|
|
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
|
|
char tmp_str[PATH_MAX];
|
|
|
|
if (!dfi_feat_seek())
|
|
ERR_EXIT("Mounting not possible for %s dumps", dfi_name());
|
|
fuse_opt_add_arg(&args, "zgetdump");
|
|
fuse_opt_add_arg(&args, "-s");
|
|
snprintf(tmp_str, sizeof(tmp_str),
|
|
"-ofsname=%s,ro,default_permissions,nonempty",
|
|
g.opts.device);
|
|
fuse_opt_add_arg(&args, tmp_str);
|
|
fuse_opt_add_arg(&args, g.opts.mount_point);
|
|
add_argv_fuse(&args);
|
|
stat_root_init();
|
|
stat_dump_init();
|
|
snprintf(l.path, sizeof(l.path), "/dump.%s", dfo_name());
|
|
return fuse_main(args.argc, args.argv, &zfuse_ops);
|
|
}
|
|
|
|
/*
|
|
* Unmount dump
|
|
*/
|
|
void zfuse_umount(void)
|
|
{
|
|
char umount_cmd[PATH_MAX];
|
|
char *umount_tool;
|
|
struct stat sbuf;
|
|
int rc;
|
|
|
|
if (stat("/usr/bin/fusermount", &sbuf) == 0)
|
|
umount_tool = "/usr/bin/fusermount -u";
|
|
else if (stat("/bin/fusermount", &sbuf) == 0)
|
|
umount_tool = "/bin/fusermount -u";
|
|
else
|
|
umount_tool = "umount";
|
|
|
|
snprintf(umount_cmd, sizeof(umount_cmd), "%s %s", umount_tool,
|
|
g.opts.mount_point);
|
|
rc = system(umount_cmd);
|
|
|
|
if (rc == -1)
|
|
ERR_EXIT_ERRNO("\"%s\" failed", umount_cmd);
|
|
if (rc > 0)
|
|
ERR_EXIT("\"%s\" failed", umount_cmd);
|
|
exit(0);
|
|
}
|