aboutsummaryrefslogtreecommitdiff
path: root/libc/sysdeps/linux/common/pread_write.c
blob: 51d76a1396471343925156c47d4c400f3844e39f (plain)
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
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
/* vi: set sw=4 ts=4: */
/*
 * Copyright (C) 2000-2006 Erik Andersen <andersen@uclibc.org>
 *
 * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
 */
/*
 * Based in part on the files
 *		./sysdeps/unix/sysv/linux/pwrite.c,
 *		./sysdeps/unix/sysv/linux/pread.c,
 *		sysdeps/posix/pread.c
 *		sysdeps/posix/pwrite.c
 * from GNU libc 2.2.5, but reworked considerably...
 */

#include <sys/syscall.h>
#include <unistd.h>
#include <stdint.h>
#include <endian.h>
#ifdef __UCLIBC_HAS_THREADS_NATIVE__
#include "sysdep-cancel.h"
#else
/* No multi-thread handling enabled.  */
#define SINGLE_THREAD_P (1)
#define RTLD_SINGLE_THREAD_P (1)
#define LIBC_CANCEL_ASYNC()	0 /* Just a dummy value.  */
#define LIBC_CANCEL_RESET(val)	((void)(val)) /* Nothing, but evaluate it.  */
#define LIBC_CANCEL_HANDLED()	/* Nothing.  */
#endif

#ifdef __NR_pread64
# undef __NR_pread
# define __NR_pread __NR_pread64
#endif
#ifdef __NR_pwrite64
# undef __NR_pwrite
# define __NR_pwrite __NR_pwrite64
#endif

#ifndef MY_PREAD
# ifdef __NR_pread
#  define __NR___syscall_pread __NR_pread
#  if defined(__UCLIBC_SYSCALL_ALIGN_64BIT__)
static _syscall6(ssize_t, __syscall_pread, int, fd, void *, buf,
                 size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo)
#   define MY_PREAD(fd, buf, count, offset) __syscall_pread(fd, buf, count, 0, OFF_HI_LO(offset))
#   define MY_PREAD64(fd, buf, count, offset) __syscall_pread(fd, buf, count, 0, OFF64_HI_LO(offset))
#  elif __WORDSIZE == 32
static _syscall5(ssize_t, __syscall_pread, int, fd, void *, buf,
                 size_t, count, off_t, offset_hi, off_t, offset_lo)
#   define MY_PREAD(fd, buf, count, offset) __syscall_pread(fd, buf, count, OFF_HI_LO(offset))
#   define MY_PREAD64(fd, buf, count, offset) __syscall_pread(fd, buf, count, OFF64_HI_LO(offset))
#  else
static _syscall4(ssize_t, __syscall_pread, int, fd, void *, buf,
                 size_t, count, off_t, offset)
#   define MY_PREAD(fd, buf, count, offset) __syscall_pread(fd, buf, count, offset)
#   define MY_PREAD64(fd, buf, count, offset) __syscall_pread(fd, buf, count, offset)
#  endif
# endif
#endif

#ifndef MY_PWRITE
# ifdef __NR_pwrite
#  define __NR___syscall_pwrite __NR_pwrite
#  if defined(__UCLIBC_SYSCALL_ALIGN_64BIT__)
static _syscall6(ssize_t, __syscall_pwrite, int, fd, const void *, buf,
                 size_t, count, int, dummy, off_t, offset_hi, off_t, offset_lo)
#   define MY_PWRITE(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, 0, OFF_HI_LO(offset))
#   define MY_PWRITE64(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, 0, OFF64_HI_LO(offset))
#  elif __WORDSIZE == 32
static _syscall5(ssize_t, __syscall_pwrite, int, fd, const void *, buf,
                 size_t, count, off_t, offset_hi, off_t, offset_lo)
#   define MY_PWRITE(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, OFF_HI_LO(offset))
#   define MY_PWRITE64(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, OFF64_HI_LO(offset))
#  else
static _syscall4(ssize_t, __syscall_pwrite, int, fd, const void *, buf,
                 size_t, count, off_t, offset)
#   define MY_PWRITE(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, offset)
#   define MY_PWRITE64(fd, buf, count, offset) __syscall_pwrite(fd, buf, count, offset)
#  endif
# endif
#endif

ssize_t __libc_pread(int fd, void *buf, size_t count, off_t offset)
{
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = MY_PREAD(fd, buf, count, offset);
	LIBC_CANCEL_RESET (oldtype);
	return result;

}
weak_alias(__libc_pread,pread)

ssize_t __libc_pwrite(int fd, const void *buf, size_t count, off_t offset)
{
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = MY_PWRITE(fd, buf, count, offset);
	LIBC_CANCEL_RESET (oldtype);
	return result;
}
weak_alias(__libc_pwrite,pwrite)

#ifdef __UCLIBC_HAS_LFS__
# if __WORDSIZE == 32
ssize_t __libc_pread64(int fd, void *buf, size_t count, off64_t offset)
{
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = MY_PREAD64(fd, buf, count, offset);
	LIBC_CANCEL_RESET (oldtype);
	return result;
}
weak_alias(__libc_pread64,pread64)

ssize_t __libc_pwrite64(int fd, const void *buf, size_t count, off64_t offset)
{
	int oldtype = LIBC_CANCEL_ASYNC ();
	int result = MY_PWRITE64(fd, buf, count, offset);
	LIBC_CANCEL_RESET (oldtype);
	return result;
}
weak_alias(__libc_pwrite64,pwrite64)

# else
#  ifdef __LINUXTHREADS_OLD__
weak_alias(pread,pread64)
weak_alias(pwrite,pwrite64)
extern __typeof(pread64) __libc_pread64;
extern __typeof(pwrite64) __libc_pwrite4;
strong_alias(pread64,__libc_pread64)
strong_alias(pwrite64,__libc_write64)
#  else
strong_alias_untyped(pread,pread64)
strong_alias_untyped(pwrite,pwrite64)
#  endif
# endif
#endif