File: offsetpreload.c

package info (click to toggle)
apptainer 1.4.4-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 12,748 kB
  • sloc: sh: 3,321; ansic: 1,706; awk: 414; python: 103; makefile: 54
file content (94 lines) | stat: -rw-r--r-- 2,847 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
/*
  Copyright (c) Contributors to the Apptainer project, established as
    Apptainer a Series of LF Projects LLC.
    For website terms of use, trademark policy, privacy policy and other
    project policies see https://lfprojects.org/policies

  This software is licensed under a 3-clause BSD license.  Please
  consult LICENSE.md file distributed with the sources of this project
  regarding your rights to use or distribute this software.
*/

/*
   LD_PRELOAD wrapper to add an offset into a file read by fuse2fs.
   Set OFFSETPRELOAD_FILE to the path of the file and OFFSETPRELOAD_OFFSET
     to the value of the offset.
   This is not general purpose, it is specific to fuse2fs.
*/

#define _GNU_SOURCE

#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include <dlfcn.h>

static int offsetfd = -3;
static long offsetval;

ssize_t pread64(int fd, void *buf, size_t count, off_t offset) {
	static off_t (*original_pread64)(int, void *, size_t, off_t) = NULL;
	if (original_pread64 == NULL) {
		original_pread64 = dlsym(RTLD_NEXT, "pread64");
	}

	if (offsetfd == fd) {
		offset += offsetval;
	}

	return (*original_pread64)(fd, buf, count, offset);
}

ssize_t pwrite64(int fd, const void *buf, size_t count, off_t offset) {
	static off_t (*original_pwrite64)(int, const void *, size_t, off_t) = NULL;
	if (original_pwrite64 == NULL) {
		original_pwrite64 = dlsym(RTLD_NEXT, "pwrite64");
	}

	if (offsetfd == fd) {
		offset += offsetval;
	}

	return (*original_pwrite64)(fd, buf, count, offset);
}

static int ___open64(int (*original_open64)(const char *, int, int, int), const char *path, int flags1, int flags2, int flags3) {
	static char *offsetpath = NULL;
	if (offsetfd == -3) {
		offsetfd = -2;
		offsetpath = getenv("OFFSETPRELOAD_FILE");
		char *valenv = getenv("OFFSETPRELOAD_OFFSET");
		if (valenv != NULL) {
			offsetval = atol(valenv);
		}
	}

	int fd = (*original_open64)(path, flags1, flags2, flags3);

	if (fd >= 0) {
		if ((offsetpath != NULL) && (strcmp(offsetpath, path) == 0)) {
			offsetfd = fd;
		}
	}

	return fd;
}

// This is the version used by some compilations of fuse2fs
int __open64_2(const char *path, int flags1, int flags2, int flags3) {
	static int (*original_open64_2)(const char*, int, int, int) = NULL;
	if (original_open64_2 == NULL) {
		original_open64_2 = dlsym(RTLD_NEXT, "__open64_2");
	}
        return ___open64(original_open64_2, path, flags1, flags2, flags3);
}

// This is more parameters than the real open64, but use that many because
// we want to use a common function with __open64_2
int open64(const char *path, int flags1, int flags2, int flags3) {
	static int (*original_open64)(const char*, int, int, int) = NULL;
	if (original_open64 == NULL) {
		original_open64 = dlsym(RTLD_NEXT, "open64");
	}
        return ___open64(original_open64, path, flags1, flags2, flags3);
}