/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- updateProcPathVirtualToReal
- updateProcPathRealToVirtual
- open
- open64
- fopen
- fopen64
- fclose
- __xstat
- __xstat64
- __fxstat
- __fxstat64
- __lxstat
- __lxstat64
- readlink
- realpath
- __realpath
- __realpath_chk
- canonicalize_file_name
- access
- ioctl
1 /****************************************************************************
2 * Copyright (C) 2006-2013 by Jason Ansel, Kapil Arya, and Gene Cooperman *
3 * jansel@csail.mit.edu, kapil@ccs.neu.edu, gene@ccs.neu.edu *
4 * *
5 * This file is part of the dmtcp/src module of DMTCP (DMTCP:dmtcp/src). *
6 * *
7 * DMTCP:dmtcp/src is free software: you can redistribute it and/or *
8 * modify it under the terms of the GNU Lesser General Public License as *
9 * published by the Free Software Foundation, either version 3 of the *
10 * License, or (at your option) any later version. *
11 * *
12 * DMTCP:dmtcp/src is distributed in the hope that it will be useful, *
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of *
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
15 * GNU Lesser General Public License for more details. *
16 * *
17 * You should have received a copy of the GNU Lesser General Public *
18 * License along with DMTCP:dmtcp/src. If not, see *
19 * <http://www.gnu.org/licenses/>. *
20 ****************************************************************************/
21
22 /* realpath is defined with "always_inline" attribute. GCC>=4.7 disallows us
23 * to define the realpath wrapper if compiled with -O0. Here we are renaming
24 * realpath so that later code does not see the declaration of realpath as
25 * inline. Normal user code from other files will continue to invoke realpath
26 * as an inline function calling __ptsname_r_chk. Later in this file
27 * we define __ptsname_r_chk to call the original realpath symbol.
28 * Similarly, for ttyname_r, etc.
29 *
30 * Also, on some machines (e.g. SLES 10), readlink has conflicting return types
31 * (ssize_t and int).
32 * In general, we rename the functions below, since any type declarations
33 * may vary on different systems, and so we ignore these type declarations.
34 */
35 #define open open_always_inline
36 #define open64 open64_always_inline
37 #define readlink readlink_always_inline
38 #define realpath realpath_always_inline
39
40 #include <stdio.h>
41 #include <stdarg.h>
42 #include <sys/ioctl.h>
43 #include <string.h>
44
45 #undef open
46 #undef open64
47 #undef readlink
48 #undef realpath
49
50 #include "jassert.h"
51 #include "jfilesystem.h"
52 #include "jconvert.h"
53 #include "pidwrappers.h"
54 #include "util.h"
55 #include "virtualpidtable.h"
56 #include "dmtcp.h"
57 #include "pid.h"
58
59 #define PROC_PREFIX "/proc/"
60
61 using namespace dmtcp;
62
63 // FIXME: This function needs third argument newpathsize, or assume PATH_MAX
64 static void updateProcPathVirtualToReal(const char *path, char **newpath)
65 {
66 if (Util::strStartsWith(path, PROC_PREFIX)) {
67 int index = strlen(PROC_PREFIX);
68 char *rest;
69 pid_t virtualPid = strtol(&path[index], &rest, 0);
70 if (virtualPid > 0 && *rest == '/') {
71 pid_t realPid = VIRTUAL_TO_REAL_PID(virtualPid);
72 sprintf(*newpath, "/proc/%d%s", realPid, rest);
73 return;
74 }
75 }
76 *newpath = (char *)path;
77 }
78
79 // FIXME: This function needs third argument newpathsize, or assume PATH_MAX
80 static void updateProcPathRealToVirtual(const char *path, char **newpath)
81 {
82 if (Util::strStartsWith(path, PROC_PREFIX)) {
83 int index = strlen(PROC_PREFIX);
84 char *rest;
85 pid_t realPid = strtol(&path[index], &rest, 0);
86 if (realPid > 0 && *rest == '/') {
87 pid_t virtualPid = REAL_TO_VIRTUAL_PID(realPid);
88 sprintf(*newpath, "/proc/%d%s", virtualPid, rest);
89 return;
90 }
91 }
92 *newpath = (char *)path;
93 return;
94 }
95
96 /* Used by open() wrapper to do other tracking of open apart from
97 synchronization stuff. */
98 extern "C" int open (const char *path, int flags, ... )
99 {
100 mode_t mode = 0;
101 // Handling the variable number of arguments
102 if (flags & O_CREAT) {
103 va_list arg;
104 va_start (arg, flags);
105 mode = va_arg (arg, int);
106 va_end (arg);
107 }
108 char tmpbuf[PATH_MAX];
109 char *newpath = tmpbuf;
110 updateProcPathVirtualToReal(path, &newpath);
111 return _real_open(newpath, flags, mode);
112 }
113
114 // FIXME: Add the 'fn64' wrapper test cases to dmtcp test suite.
115 extern "C" int open64 (const char *path, int flags, ... )
116 {
117 mode_t mode = 0;
118 // Handling the variable number of arguments
119 if (flags & O_CREAT) {
120 va_list arg;
121 va_start (arg, flags);
122 mode = va_arg (arg, int);
123 va_end (arg);
124 }
125 char tmpbuf[PATH_MAX];
126 char *newpath = tmpbuf;
127 updateProcPathVirtualToReal(path, &newpath);
128 return _real_open64(newpath, flags, mode);
129 }
130
131 extern "C" FILE *fopen (const char* path, const char* mode)
132 {
133 char tmpbuf[PATH_MAX];
134 char *newpath = tmpbuf;
135 updateProcPathVirtualToReal(path, &newpath);
136 return _real_fopen(newpath, mode);
137 }
138
139 extern "C" FILE *fopen64 (const char* path, const char* mode)
140 {
141 char tmpbuf[PATH_MAX];
142 char *newpath = tmpbuf;
143 updateProcPathVirtualToReal(path, &newpath);
144 return _real_fopen64(newpath, mode);
145 }
146
147 extern "C" int fclose(FILE *fp)
148 {
149 // This wrapper is needed to ensure that we call the "GLIBC_2.1" version in
150 // 32-bit systems. Ideally, this should be done only in the plugin that uses
151 // fclose (e.g. File plugin), but doing it here will work as well.
152 return _real_fclose(fp);
153 }
154
155 extern "C" int __xstat(int vers, const char *path, struct stat *buf)
156 {
157 char tmpbuf[PATH_MAX];
158 char *newpath = tmpbuf;
159 updateProcPathVirtualToReal(path, &newpath);
160 int retval = _real_xstat( vers, newpath, buf );
161 return retval;
162 }
163
164 extern "C" int __xstat64(int vers, const char *path, struct stat64 *buf)
165 {
166 char tmpbuf[PATH_MAX];
167 char *newpath = tmpbuf;
168 updateProcPathVirtualToReal(path, &newpath);
169 int retval = _real_xstat64( vers, newpath, buf );
170 return retval;
171 }
172
173 #if 0
174 extern "C" int __fxstat(int vers, int fd, struct stat *buf)
175 {
176 int retval = _real_fxstat(vers, fd, buf);
177 return retval;
178 }
179
180 extern "C" int __fxstat64(int vers, int fd, struct stat64 *buf)
181 {
182 int retval = _real_fxstat64(vers, fd, buf);
183 return retval;
184 }
185 #endif
186
187 extern "C" int __lxstat(int vers, const char *path, struct stat *buf)
188 {
189 char tmpbuf[PATH_MAX];
190 char *newpath = tmpbuf;
191 updateProcPathVirtualToReal(path, &newpath);
192 int retval = _real_lxstat( vers, newpath, buf );
193 return retval;
194 }
195
196 extern "C" int __lxstat64(int vers, const char *path, struct stat64 *buf)
197 {
198 char tmpbuf[PATH_MAX];
199 char *newpath = tmpbuf;
200 updateProcPathVirtualToReal(path, &newpath);
201 int retval = _real_lxstat64( vers, newpath, buf );
202 return retval;
203 }
204
205 extern "C" ssize_t readlink(const char *path, char *buf, size_t bufsiz)
206 {
207 char tmpbuf[PATH_MAX];
208 char *newpath = tmpbuf;
209 //FIXME: Suppose the real path is longer than PATH_MAX. Do we check?
210 updateProcPathVirtualToReal(path, &newpath);
211 return NEXT_FNC(readlink) (newpath, buf, bufsiz);
212 #if 0
213 if (ret != -1) {
214 JASSERT(ret < bufsiz)(ret)(bufsiz)(buf)(newpath);
215 buf[ret] = '\0'; // glibc-2.13: readlink doesn't terminate buf w/ null char
216 updateProcPathRealToVirtual(buf, newpath);
217 JASSERT(strlen(newpath) < bufsiz)(newpath)(bufsiz);
218 strcpy(buf, newpath);
219 }
220 return ret;
221 #endif
222 }
223
224 extern "C" char *realpath(const char *path, char *resolved_path)
225 {
226 char tmpbuf[PATH_MAX];
227 char *newpath = tmpbuf;
228 updateProcPathVirtualToReal(path, &newpath);
229 // Required for matlab-2012 and later; realpath is a versioned symbol.
230 char *retval = NEXT_FNC_DEFAULT(realpath) (newpath, resolved_path);
231 if (retval != NULL) {
232 updateProcPathRealToVirtual(retval, &newpath);
233 strcpy(retval, newpath);
234 }
235 return retval;
236 }
237
238 extern "C" char *__realpath(const char *path, char *resolved_path)
239 {
240 return realpath(path, resolved_path);
241 }
242
243 extern "C" char *__realpath_chk(const char *path, char *resolved_path,
244 size_t resolved_len)
245 {
246 return realpath(path, resolved_path);
247 }
248
249 extern "C" char *canonicalize_file_name(const char *path)
250 {
251 return realpath(path, NULL);
252 }
253
254 #include <unistd.h>
255 extern "C" int access(const char *path, int mode)
256 {
257 char tmpbuf[PATH_MAX];
258 char *newpath = tmpbuf;
259 updateProcPathVirtualToReal(path, &newpath);
260 return NEXT_FNC(access) (newpath, mode);
261 }
262
263 // TODO: ioctl must use virtualized pids for request = TIOCGPGRP / TIOCSPGRP
264 // These are synonyms for POSIX standard tcgetpgrp / tcsetpgrp
265 extern "C" {
266 int send_sigwinch = 0;
267 }
268
269
270 extern "C" int ioctl(int d, unsigned long int request, ...)
271 {
272 va_list ap;
273 int retval;
274
275 if (send_sigwinch && request == TIOCGWINSZ) {
276 send_sigwinch = 0;
277 va_list local_ap;
278 va_copy(local_ap, ap);
279 va_start(local_ap, request);
280 struct winsize * win = va_arg(local_ap, struct winsize *);
281 va_end(local_ap);
282 retval = _real_ioctl(d, request, win); // This fills in win
283 win->ws_col--; // Lie to application, and force it to resize window,
284 // reset any scroll regions, etc.
285 kill(getpid(), SIGWINCH); // Tell application to look up true winsize
286 // and resize again.
287 } else {
288 void * arg;
289 va_start(ap, request);
290 arg = va_arg(ap, void *);
291 va_end(ap);
292 retval = _real_ioctl(d, request, arg);
293 }
294 return retval;
295 }