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#pragma ident	"%Z%%M%	%I%	%E% SMI"
28
29#include <stdlib.h>
30#include <unistd.h>
31#include <errno.h>
32#include "libproc.h"
33
34typedef union {
35	offset_t	full;		/* full 64 bit offset value */
36	uint32_t	half[2];	/* two 32-bit halves */
37} offsets_t;
38
39/*
40 * lseek() system call -- executed by subject process.
41 */
42off_t
43pr_lseek(struct ps_prochandle *Pr, int filedes, off_t offset, int whence)
44{
45	int syscall;		/* SYS_lseek or SYS_llseek */
46	int nargs;		/* 3 or 4, depending on syscall */
47	offsets_t off;
48	sysret_t rval;		/* return value from lseek() */
49	argdes_t argd[4];	/* arg descriptors for lseek() */
50	argdes_t *adp;
51	int error;
52
53	if (Pr == NULL)
54		return (lseek(filedes, offset, whence));
55
56	adp = &argd[0];		/* filedes argument */
57	adp->arg_value = filedes;
58	adp->arg_object = NULL;
59	adp->arg_type = AT_BYVAL;
60	adp->arg_inout = AI_INPUT;
61	adp->arg_size = 0;
62
63	adp++;			/* offset argument */
64	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_NATIVE) {
65		syscall = SYS_lseek;
66		nargs = 3;
67		adp->arg_value = offset;
68		adp->arg_object = NULL;
69		adp->arg_type = AT_BYVAL;
70		adp->arg_inout = AI_INPUT;
71		adp->arg_size = 0;
72	} else {
73		syscall = SYS_llseek;
74		nargs = 4;
75		off.full = offset;
76		adp->arg_value = off.half[0];	/* first 32 bits */
77		adp->arg_object = NULL;
78		adp->arg_type = AT_BYVAL;
79		adp->arg_inout = AI_INPUT;
80		adp->arg_size = 0;
81		adp++;
82		adp->arg_value = off.half[1];	/* second 32 bits */
83		adp->arg_object = NULL;
84		adp->arg_type = AT_BYVAL;
85		adp->arg_inout = AI_INPUT;
86		adp->arg_size = 0;
87	}
88
89	adp++;			/* whence argument */
90	adp->arg_value = whence;
91	adp->arg_object = NULL;
92	adp->arg_type = AT_BYVAL;
93	adp->arg_inout = AI_INPUT;
94	adp->arg_size = 0;
95
96	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
97
98	if (error) {
99		errno = (error > 0)? error : ENOSYS;
100		return ((off_t)(-1));
101	}
102
103	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_NATIVE)
104		offset = rval.sys_rval1;
105	else {
106		off.half[0] = (uint32_t)rval.sys_rval1;
107		off.half[1] = (uint32_t)rval.sys_rval2;
108		offset = (off_t)off.full;
109	}
110
111	return (offset);
112}
113
114/*
115 * llseek() system call -- executed by subject process.
116 */
117offset_t
118pr_llseek(struct ps_prochandle *Pr, int filedes, offset_t offset, int whence)
119{
120	int syscall;		/* SYS_lseek or SYS_llseek */
121	int nargs;		/* 3 or 4, depending on syscall */
122	offsets_t off;
123	sysret_t rval;		/* return value from llseek() */
124	argdes_t argd[4];	/* arg descriptors for llseek() */
125	argdes_t *adp;
126	int error;
127
128	if (Pr == NULL)
129		return (llseek(filedes, offset, whence));
130
131	adp = &argd[0];		/* filedes argument */
132	adp->arg_value = filedes;
133	adp->arg_object = NULL;
134	adp->arg_type = AT_BYVAL;
135	adp->arg_inout = AI_INPUT;
136	adp->arg_size = 0;
137
138	adp++;			/* offset argument */
139	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64) {
140		syscall = SYS_lseek;
141		nargs = 3;
142		adp->arg_value = offset;
143		adp->arg_object = NULL;
144		adp->arg_type = AT_BYVAL;
145		adp->arg_inout = AI_INPUT;
146		adp->arg_size = 0;
147	} else {
148		syscall = SYS_llseek;
149		nargs = 4;
150		off.full = offset;
151		adp->arg_value = off.half[0];	/* first 32 bits */
152		adp->arg_object = NULL;
153		adp->arg_type = AT_BYVAL;
154		adp->arg_inout = AI_INPUT;
155		adp->arg_size = 0;
156		adp++;
157		adp->arg_value = off.half[1];	/* second 32 bits */
158		adp->arg_object = NULL;
159		adp->arg_type = AT_BYVAL;
160		adp->arg_inout = AI_INPUT;
161		adp->arg_size = 0;
162	}
163
164	adp++;			/* whence argument */
165	adp->arg_value = whence;
166	adp->arg_object = NULL;
167	adp->arg_type = AT_BYVAL;
168	adp->arg_inout = AI_INPUT;
169	adp->arg_size = 0;
170
171	error = Psyscall(Pr, &rval, syscall, nargs, &argd[0]);
172
173	if (error) {
174		errno = (error > 0)? error : ENOSYS;
175		return ((offset_t)(-1));
176	}
177
178	if (Pstatus(Pr)->pr_dmodel == PR_MODEL_LP64)
179		offset = rval.sys_rval1;
180	else {
181		off.half[0] = (uint32_t)rval.sys_rval1;
182		off.half[1] = (uint32_t)rval.sys_rval2;
183		offset = off.full;
184	}
185
186	return (offset);
187}
188