xref: /illumos-gate/usr/src/lib/libproc/common/pr_lseek.c (revision 581cede61ac9c14d8d4ea452562a567189eead78)
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 
34 typedef 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  */
42 off_t
43 pr_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  */
117 offset_t
118 pr_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