1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 */
22 /*
23 * Copyright (c) 1998-2000 by Sun Microsystems, Inc.
24 * All rights reserved.
25 */
26
27 #include <stdlib.h>
28 #include <unistd.h>
29 #include <errno.h>
30 #include "libproc.h"
31
32 typedef union {
33 offset_t full; /* full 64 bit offset value */
34 uint32_t half[2]; /* two 32-bit halves */
35 } offsets_t;
36
37 /*
38 * lseek() system call -- executed by subject process.
39 */
40 off_t
pr_lseek(struct ps_prochandle * Pr,int filedes,off_t offset,int whence)41 pr_lseek(struct ps_prochandle *Pr, int filedes, off_t offset, int whence)
42 {
43 int syscall; /* SYS_lseek or SYS_llseek */
44 int nargs; /* 3 or 4, depending on syscall */
45 offsets_t off;
46 sysret_t rval; /* return value from lseek() */
47 argdes_t argd[4]; /* arg descriptors for lseek() */
48 argdes_t *adp;
49 int error;
50
51 if (Pr == NULL)
52 return (lseek(filedes, offset, whence));
53
54 adp = &argd[0]; /* filedes argument */
55 adp->arg_value = filedes;
56 adp->arg_object = NULL;
57 adp->arg_type = AT_BYVAL;
58 adp->arg_inout = AI_INPUT;
59 adp->arg_size = 0;
60
61 adp++; /* offset argument */
62 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_NATIVE) {
63 syscall = SYS_lseek;
64 nargs = 3;
65 adp->arg_value = offset;
66 adp->arg_object = NULL;
67 adp->arg_type = AT_BYVAL;
68 adp->arg_inout = AI_INPUT;
69 adp->arg_size = 0;
70 } else {
71 syscall = SYS_llseek;
72 nargs = 4;
73 off.full = offset;
74 adp->arg_value = off.half[0]; /* first 32 bits */
75 adp->arg_object = NULL;
76 adp->arg_type = AT_BYVAL;
77 adp->arg_inout = AI_INPUT;
78 adp->arg_size = 0;
79 adp++;
80 adp->arg_value = off.half[1]; /* second 32 bits */
81 adp->arg_object = NULL;
82 adp->arg_type = AT_BYVAL;
83 adp->arg_inout = AI_INPUT;
84 adp->arg_size = 0;
85 }
86
87 adp++; /* whence argument */
88 adp->arg_value = whence;
89 adp->arg_object = NULL;
90 adp->arg_type = AT_BYVAL;
91 adp->arg_inout = AI_INPUT;
92 adp->arg_size = 0;
93
94 error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
95
96 if (error) {
97 errno = (error > 0)? error : ENOSYS;
98 return ((off_t)(-1));
99 }
100
101 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_NATIVE)
102 offset = rval.sys_rval1;
103 else {
104 off.half[0] = (uint32_t)rval.sys_rval1;
105 off.half[1] = (uint32_t)rval.sys_rval2;
106 offset = (off_t)off.full;
107 }
108
109 return (offset);
110 }
111
112 /*
113 * llseek() system call -- executed by subject process.
114 */
115 offset_t
pr_llseek(struct ps_prochandle * Pr,int filedes,offset_t offset,int whence)116 pr_llseek(struct ps_prochandle *Pr, int filedes, offset_t offset, int whence)
117 {
118 int syscall; /* SYS_lseek or SYS_llseek */
119 int nargs; /* 3 or 4, depending on syscall */
120 offsets_t off;
121 sysret_t rval; /* return value from llseek() */
122 argdes_t argd[4]; /* arg descriptors for llseek() */
123 argdes_t *adp;
124 int error;
125
126 if (Pr == NULL)
127 return (llseek(filedes, offset, whence));
128
129 adp = &argd[0]; /* filedes argument */
130 adp->arg_value = filedes;
131 adp->arg_object = NULL;
132 adp->arg_type = AT_BYVAL;
133 adp->arg_inout = AI_INPUT;
134 adp->arg_size = 0;
135
136 adp++; /* offset argument */
137 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) {
138 syscall = SYS_lseek;
139 nargs = 3;
140 adp->arg_value = offset;
141 adp->arg_object = NULL;
142 adp->arg_type = AT_BYVAL;
143 adp->arg_inout = AI_INPUT;
144 adp->arg_size = 0;
145 } else {
146 syscall = SYS_llseek;
147 nargs = 4;
148 off.full = offset;
149 adp->arg_value = off.half[0]; /* first 32 bits */
150 adp->arg_object = NULL;
151 adp->arg_type = AT_BYVAL;
152 adp->arg_inout = AI_INPUT;
153 adp->arg_size = 0;
154 adp++;
155 adp->arg_value = off.half[1]; /* second 32 bits */
156 adp->arg_object = NULL;
157 adp->arg_type = AT_BYVAL;
158 adp->arg_inout = AI_INPUT;
159 adp->arg_size = 0;
160 }
161
162 adp++; /* whence argument */
163 adp->arg_value = whence;
164 adp->arg_object = NULL;
165 adp->arg_type = AT_BYVAL;
166 adp->arg_inout = AI_INPUT;
167 adp->arg_size = 0;
168
169 error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
170
171 if (error) {
172 errno = (error > 0)? error : ENOSYS;
173 return ((offset_t)(-1));
174 }
175
176 if (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64)
177 offset = rval.sys_rval1;
178 else {
179 off.half[0] = (uint32_t)rval.sys_rval1;
180 off.half[1] = (uint32_t)rval.sys_rval2;
181 offset = off.full;
182 }
183
184 return (offset);
185 }
186