/* [<][>][^][v][top][bottom][index][help] */
DEFINITIONS
This source file includes following definitions.
- close
- fclose
- closedir
- dup
- dup2
- dup3
- ptsname_r_work
- ptsname_r
- ptsname
- __ptsname_r_chk
- ttyname_r
- ttyname
- __ttyname_r_chk
- getpt
- posix_openpt
- tmpfile
- mkstemp
- mkostemp
- mkstemps
- mkostemps
- _open_open64_work
- open
- __open_2
- open64
- __open64_2
- creat
- creat64
- _fopen_fopen64_work
- fopen
- fopen64
- freopen
- openat
- openat_2
- __openat_2
- openat64
- openat64_2
- __openat64_2
- opendir
- updateStatPath
- __xstat
- __xstat64
- __fxstat
- __fxstat64
- __lxstat
- __lxstat64
- readlink
- __readlink_chk
- fcntl
- realpath
- __realpath
- __realpath_chk
- canonicalize_file_name
- access
- ioctl
1 /****************************************************************************
2 * Copyright (C) 2006-2010 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 /* ptsname_r is defined with "always_inline" attribute. GCC>=4.7 disallows us
23 * to define the ptsname_r wrapper if compiled with -O0. Here we are renaming
24 * ptsname_r so that later code does not see the declaration of ptsname_r as
25 * inline. Normal user code from other files will continue to invoke ptsname_r
26 * as inline as an inline function calling __ptsname_r_chk. Later in this file
27 * we define __ptsname_r_chk to call the original ptsname_r 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 ptsname_r ptsname_r_always_inline
36 #define ttyname_r ttyname_r_always_inline
37 #define open open_always_inline
38 #define open64 open64_always_inline
39 #define openat openat_always_inline
40 #define openat64 openat64_always_inline
41 #define readlink readlink_always_inline
42 #define __readlink_chk _ret__readlink_chk
43 #define realpath realpath_always_inline
44
45 #include <stdarg.h>
46 #include <stdlib.h>
47 #include <vector>
48 #include <list>
49 #include <string>
50 #include <fcntl.h>
51 #include <signal.h>
52 #include <sys/ipc.h>
53 #include <sys/shm.h>
54 #include <sys/types.h>
55 #include <sys/socket.h>
56 #include <sys/ioctl.h>
57 #include <unistd.h>
58 #include <dirent.h>
59 #include <sys/syscall.h>
60 #include <linux/version.h>
61 #include <limits.h>
62
63 #undef ptsname_r
64 #undef ttyname_r
65 #undef open
66 #undef open64
67 #undef openat
68 #undef openat64
69 #undef readlink
70 #undef __readlink_chk
71 #undef realpath
72
73 #include "dmtcp.h"
74 #include "shareddata.h"
75 #include "util.h"
76 #include "jassert.h"
77 #include "jconvert.h"
78 #include "jfilesystem.h"
79
80 #include "fileconnlist.h"
81 #include "fileconnection.h"
82 #include "filewrappers.h"
83
84 using namespace dmtcp;
85 #if 0
86 extern "C" int close(int fd)
87 {
88 if (dmtcp_is_protected_fd(fd)) {
89 JTRACE("blocked attempt to close protected fd") (fd);
90 errno = EBADF;
91 return -1;
92 }
93
94 DMTCP_PLUGIN_DISABLE_CKPT();
95 int rv = _real_close(fd);
96 if (rv == 0 && dmtcp_is_running_state()) {
97 FileConnList::instance().processClose(fd);
98 }
99 DMTCP_PLUGIN_ENABLE_CKPT();
100 return rv;
101 }
102
103 extern "C" int fclose(FILE *fp)
104 {
105 int fd = fileno(fp);
106 if (dmtcp_is_protected_fd(fd)) {
107 JTRACE("blocked attempt to fclose protected fd") (fd);
108 errno = EBADF;
109 return -1;
110 }
111
112 DMTCP_PLUGIN_DISABLE_CKPT();
113 int rv = _real_fclose(fp);
114 if (rv == 0 && dmtcp_is_running_state()) {
115 FileConnList::instance().processClose(fd);
116 }
117 DMTCP_PLUGIN_ENABLE_CKPT();
118
119 return rv;
120 }
121
122 extern "C" int closedir(DIR *dir)
123 {
124 int fd = dirfd(dir);
125 if (dmtcp_is_protected_fd(fd)) {
126 JTRACE("blocked attempt to closedir protected fd") (fd);
127 errno = EBADF;
128 return -1;
129 }
130
131 DMTCP_PLUGIN_DISABLE_CKPT();
132 int rv = _real_closedir(dir);
133 if (rv == 0 && dmtcp_is_running_state()) {
134 FileConnList::instance().processClose(fd);
135 }
136 DMTCP_PLUGIN_ENABLE_CKPT();
137
138 return rv;
139 }
140
141 extern "C" int dup(int oldfd)
142 {
143 DMTCP_PLUGIN_DISABLE_CKPT();
144 int newfd = _real_dup(oldfd);
145 if (newfd != -1 && dmtcp_is_running_state()) {
146 FileConnList::instance().processDup(oldfd, newfd);
147 }
148 DMTCP_PLUGIN_ENABLE_CKPT();
149 return newfd;
150 }
151
152 extern "C" int dup2(int oldfd, int newfd)
153 {
154 DMTCP_PLUGIN_DISABLE_CKPT();
155 int res = _real_dup2(oldfd, newfd);
156 if (res != -1 && newfd != oldfd && dmtcp_is_running_state()) {
157 FileConnList::instance().processDup(oldfd, newfd);
158 }
159 DMTCP_PLUGIN_ENABLE_CKPT();
160 return newfd;
161 }
162
163 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,27)) && __GLIBC_PREREQ(2,9)
164 // dup3 appeared in Linux 2.6.27
165 extern "C" int dup3(int oldfd, int newfd, int flags)
166 {
167 DMTCP_PLUGIN_DISABLE_CKPT();
168 int res = _real_dup3(oldfd, newfd, flags);
169 if (res != -1 && newfd != oldfd && dmtcp_is_running_state()) {
170 FileConnList::instance().processDup(oldfd, newfd);
171 }
172 DMTCP_PLUGIN_ENABLE_CKPT();
173 return newfd;
174 }
175 #endif
176 #endif
177
178 static int ptsname_r_work(int fd, char * buf, size_t buflen)
179 {
180 JTRACE("Calling ptsname_r");
181
182 Connection* c = FileConnList::instance().getConnection(fd);
183 PtyConnection* ptyCon =(PtyConnection*) c;
184
185 string virtPtsName = ptyCon->virtPtsName();
186
187 JTRACE("ptsname_r") (virtPtsName);
188
189 if (virtPtsName.length() >= buflen)
190 {
191 JWARNING(false) (virtPtsName) (virtPtsName.length()) (buflen)
192 .Text("fake ptsname() too long for user buffer");
193 errno = ERANGE;
194 return -1;
195 }
196
197 strcpy(buf, virtPtsName.c_str());
198
199 return 0;
200 }
201
202 extern "C" int ptsname_r(int fd, char * buf, size_t buflen)
203 {
204 DMTCP_PLUGIN_DISABLE_CKPT();
205
206 int retVal = ptsname_r_work(fd, buf, buflen);
207
208 DMTCP_PLUGIN_ENABLE_CKPT();
209
210 return retVal;
211 }
212
213 extern "C" char *ptsname(int fd)
214 {
215 /* No need to acquire Wrapper Protection lock since it will be done in ptsname_r */
216 JTRACE("ptsname() promoted to ptsname_r()");
217 static char tmpbuf[PATH_MAX];
218
219 if (ptsname_r(fd, tmpbuf, sizeof(tmpbuf)) != 0)
220 {
221 return NULL;
222 }
223
224 return tmpbuf;
225 }
226
227 extern "C" int __ptsname_r_chk(int fd, char * buf, size_t buflen, size_t nreal)
228 {
229 DMTCP_PLUGIN_DISABLE_CKPT();
230
231 JASSERT(buflen <= nreal) (buflen) (nreal) .Text("Buffer Overflow detected!");
232
233 int retVal = ptsname_r_work(fd, buf, buflen);
234
235 DMTCP_PLUGIN_ENABLE_CKPT();
236
237 return retVal;
238 }
239
240 extern "C" int ttyname_r(int fd, char *buf, size_t buflen)
241 {
242 char tmpbuf[64];
243 DMTCP_PLUGIN_DISABLE_CKPT();
244 int ret = _real_ttyname_r(fd, tmpbuf, sizeof(tmpbuf));
245
246 if (ret == 0 && strcmp(tmpbuf, "/dev/tty") != 0) {
247 Connection* c = FileConnList::instance().getConnection(fd);
248 JASSERT(c != NULL) (fd) (tmpbuf);
249 PtyConnection* ptyCon =(PtyConnection*) c;
250 string virtPtsName = ptyCon->virtPtsName();
251
252 if (virtPtsName.length() >= buflen) {
253 JWARNING(false) (virtPtsName) (virtPtsName.length()) (buflen)
254 .Text("fake ptsname() too long for user buffer");
255 errno = ERANGE;
256 ret = -1;
257 } else {
258 strncpy(buf, virtPtsName.c_str(), buflen);
259 }
260 }
261 DMTCP_PLUGIN_ENABLE_CKPT();
262
263 return ret;
264 }
265
266 extern "C" char *ttyname(int fd)
267 {
268 static char tmpbuf[64];
269
270 if (ttyname_r(fd, tmpbuf, sizeof(tmpbuf)) != 0) {
271 return NULL;
272 }
273 return tmpbuf;
274 }
275
276 extern "C" int __ttyname_r_chk(int fd, char *buf, size_t buflen, size_t nreal)
277 {
278 return ttyname_r(fd, buf, buflen);
279 }
280
281 extern "C" int getpt()
282 {
283 DMTCP_PLUGIN_DISABLE_CKPT();
284 int fd = _real_getpt();
285 if (fd >= 0 && dmtcp_is_running_state()) {
286 FileConnList::instance().processFileConnection(fd, "/dev/ptmx",
287 O_RDWR | O_NOCTTY, -1);
288 }
289 DMTCP_PLUGIN_ENABLE_CKPT();
290 return fd;
291 }
292
293 extern "C" int posix_openpt(int flags)
294 {
295 DMTCP_PLUGIN_DISABLE_CKPT();
296 int fd = _real_posix_openpt(flags);
297 if (fd >= 0 && dmtcp_is_running_state()) {
298 FileConnList::instance().processFileConnection(fd, "/dev/ptmx",
299 flags, -1);
300 }
301 DMTCP_PLUGIN_ENABLE_CKPT();
302 return fd;
303 }
304
305 extern "C" FILE *tmpfile()
306 {
307 DMTCP_PLUGIN_DISABLE_CKPT();
308 FILE *fp = _real_tmpfile();
309 if (fp != NULL && dmtcp_is_running_state()) {
310 FileConnList::instance().processFileConnection(fileno(fp), NULL, O_RDWR, 0600);
311 }
312 DMTCP_PLUGIN_ENABLE_CKPT();
313 return fp;
314 }
315
316 extern "C" int mkstemp(char *ttemplate)
317 {
318 DMTCP_PLUGIN_DISABLE_CKPT();
319 int fd = _real_mkstemp(ttemplate);
320 if (fd >= 0 && dmtcp_is_running_state()) {
321 FileConnList::instance().processFileConnection(fd, NULL, O_RDWR, 0600);
322 }
323 DMTCP_PLUGIN_ENABLE_CKPT();
324 return fd;
325 }
326
327 extern "C" int mkostemp(char *ttemplate, int flags)
328 {
329 DMTCP_PLUGIN_DISABLE_CKPT();
330 int fd = _real_mkostemp(ttemplate, flags);
331 if (fd >= 0 && dmtcp_is_running_state()) {
332 FileConnList::instance().processFileConnection(fd, NULL, flags, 0600);
333 }
334 DMTCP_PLUGIN_ENABLE_CKPT();
335 return fd;
336 }
337
338 extern "C" int mkstemps(char *ttemplate, int suffixlen)
339 {
340 DMTCP_PLUGIN_DISABLE_CKPT();
341 int fd = _real_mkstemps(ttemplate, suffixlen);
342 if (fd >= 0 && dmtcp_is_running_state()) {
343 FileConnList::instance().processFileConnection(fd, NULL, O_RDWR, 0600);
344 }
345 DMTCP_PLUGIN_ENABLE_CKPT();
346 return fd;
347 }
348
349 extern "C" int mkostemps(char *ttemplate, int suffixlen, int flags)
350 {
351 DMTCP_PLUGIN_DISABLE_CKPT();
352 int fd = _real_mkostemps(ttemplate, suffixlen, flags);
353 if (fd >= 0 && dmtcp_is_running_state()) {
354 FileConnList::instance().processFileConnection(fd, NULL, flags, 0600);
355 }
356 DMTCP_PLUGIN_ENABLE_CKPT();
357 return fd;
358 }
359
360 static int _open_open64_work(int(*fn) (const char *path, int flags, ...),
361 const char *path, int flags, mode_t mode)
362 {
363 char currPtsDevName[32];
364 const char *newpath = path;
365
366 DMTCP_PLUGIN_DISABLE_CKPT();
367
368 if (Util::strStartsWith(path, VIRT_PTS_PREFIX_STR)) {
369 SharedData::getRealPtyName(path, currPtsDevName,
370 sizeof(currPtsDevName));
371 newpath = currPtsDevName;
372 }
373
374 int fd = (*fn) (newpath, flags, mode);
375
376 if (fd >= 0 && dmtcp_is_running_state()) {
377 FileConnList::instance().processFileConnection(fd, newpath, flags, mode);
378 }
379
380 DMTCP_PLUGIN_ENABLE_CKPT();
381
382 return fd;
383 }
384
385 /* Used by open() wrapper to do other tracking of open apart from
386 synchronization stuff. */
387 extern "C" int open(const char *path, int flags, ...)
388 {
389 mode_t mode = 0;
390 // Handling the variable number of arguments
391 if (flags & O_CREAT) {
392 va_list arg;
393 va_start(arg, flags);
394 mode = va_arg(arg, int);
395 va_end(arg);
396 }
397 return _open_open64_work(_real_open, path, flags, mode);
398 }
399
400 extern "C" int __open_2(const char *path, int flags)
401 {
402 return _open_open64_work(_real_open, path, flags, 0);
403 }
404
405 // FIXME: The 'fn64' version of functions is defined only when within
406 // __USE_LARGEFILE64 is #defined. The wrappers in this file need to consider
407 // this fact. The problem can occur, for example, when DMTCP is not compiled
408 // with __USE_LARGEFILE64 whereas the user-binary is. In that case the open64()
409 // call from user will come to DMTCP and DMTCP might fail to execute it
410 // properly.
411
412 // FIXME: Add the 'fn64' wrapper test cases to dmtcp test suite.
413 extern "C" int open64(const char *path, int flags, ...)
414 {
415 mode_t mode = 0;
416 // Handling the variable number of arguments
417 if (flags & O_CREAT) {
418 va_list arg;
419 va_start(arg, flags);
420 mode = va_arg(arg, int);
421 va_end(arg);
422 }
423 return _open_open64_work(_real_open64, path, flags, mode);
424 }
425
426 extern "C" int __open64_2(const char *path, int flags)
427 {
428 return _open_open64_work(_real_open64, path, flags, 0);
429 }
430
431 extern "C" int creat(const char *path, mode_t mode)
432 {
433 //creat() is equivalent to open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC
434 return _open_open64_work(_real_open, path, O_CREAT|O_WRONLY|O_TRUNC, mode);
435 }
436
437 extern "C" int creat64(const char *path, mode_t mode)
438 {
439 //creat() is equivalent to open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC
440 return _open_open64_work(_real_open64, path, O_CREAT|O_WRONLY|O_TRUNC, mode);
441 }
442
443 static FILE *_fopen_fopen64_work(FILE*(*fn) (const char *path, const char *mode),
444 const char *path, const char *mode)
445 {
446 char currPtsDevName[32];
447 const char *newpath = path;
448
449 DMTCP_PLUGIN_DISABLE_CKPT();
450
451 if (Util::strStartsWith(path, VIRT_PTS_PREFIX_STR)) {
452 SharedData::getRealPtyName(path, currPtsDevName,
453 sizeof(currPtsDevName));
454 newpath = currPtsDevName;
455 }
456
457 FILE *file =(*fn) (newpath, mode);
458
459 if (file != NULL && dmtcp_is_running_state()) {
460 FileConnList::instance().processFileConnection(fileno(file), newpath,
461 -1, -1);
462 }
463
464 DMTCP_PLUGIN_ENABLE_CKPT();
465 return file;
466 }
467
468 extern "C" FILE *fopen(const char* path, const char* mode)
469 {
470 return _fopen_fopen64_work(_real_fopen, path, mode);
471 }
472
473 extern "C" FILE *fopen64(const char* path, const char* mode)
474 {
475 return _fopen_fopen64_work(_real_fopen64, path, mode);
476 }
477
478 extern "C" FILE *freopen(const char *path, const char *mode, FILE *stream)
479 {
480 char currPtsDevName[32];
481 const char *newpath = path;
482
483 DMTCP_PLUGIN_DISABLE_CKPT();
484
485 if (Util::strStartsWith(path, VIRT_PTS_PREFIX_STR)) {
486 SharedData::getRealPtyName(path, currPtsDevName,
487 sizeof(currPtsDevName));
488 newpath = currPtsDevName;
489 }
490
491 FILE *file = _real_freopen(newpath, mode, stream);
492
493 if (file != NULL && dmtcp_is_running_state()) {
494 FileConnList::instance().processFileConnection(fileno(file), newpath,
495 -1, -1);
496 }
497
498 DMTCP_PLUGIN_ENABLE_CKPT();
499 return file;
500 }
501
502 extern "C" int openat(int dirfd, const char *path, int flags, ...)
503 {
504 va_list arg;
505 va_start(arg, flags);
506 mode_t mode = va_arg(arg, int);
507 va_end(arg);
508 DMTCP_PLUGIN_DISABLE_CKPT();
509 int fd = _real_openat(dirfd, path, flags, mode);
510 if (fd >= 0 && dmtcp_is_running_state()) {
511 string procpath = "/proc/self/fd/" + jalib::XToString(fd);
512 string device = jalib::Filesystem::ResolveSymlink(procpath);
513 FileConnList::instance().processFileConnection(fd, device.c_str(),
514 flags, mode);
515 }
516 DMTCP_PLUGIN_ENABLE_CKPT();
517 return fd;
518 }
519
520 extern "C" int openat_2(int dirfd, const char *path, int flags)
521 {
522 return openat(dirfd, path, flags, 0);
523 }
524
525 extern "C" int __openat_2(int dirfd, const char *path, int flags)
526 {
527 return openat(dirfd, path, flags, 0);
528 }
529
530 extern "C" int openat64(int dirfd, const char *path, int flags, ...)
531 {
532 va_list arg;
533 va_start(arg, flags);
534 mode_t mode = va_arg(arg, int);
535 va_end(arg);
536 DMTCP_PLUGIN_DISABLE_CKPT();
537 int fd = _real_openat64(dirfd, path, flags, mode);
538 if (fd >= 0 && dmtcp_is_running_state()) {
539 string procpath = "/proc/self/fd/" + jalib::XToString(fd);
540 string device = jalib::Filesystem::ResolveSymlink(procpath);
541 FileConnList::instance().processFileConnection(fd, device.c_str(),
542 flags, mode);
543 }
544 DMTCP_PLUGIN_ENABLE_CKPT();
545 return fd;
546 }
547
548 extern "C" int openat64_2(int dirfd, const char *path, int flags)
549 {
550 return openat64(dirfd, path, flags, 0);
551 }
552
553 extern "C" int __openat64_2(int dirfd, const char *path, int flags)
554 {
555 return openat64(dirfd, path, flags, 0);
556 }
557
558 extern "C" DIR *opendir(const char *name)
559 {
560 DMTCP_PLUGIN_DISABLE_CKPT();
561 DIR *dir = _real_opendir(name);
562 if (dir != NULL && dmtcp_is_running_state()) {
563 FileConnList::instance().processFileConnection(dirfd(dir), name, -1, -1);
564 }
565 DMTCP_PLUGIN_ENABLE_CKPT();
566 return dir;
567 }
568
569 static void updateStatPath(const char *path, char **newpath)
570 {
571 if (Util::strStartsWith(path, VIRT_PTS_PREFIX_STR)) {
572 char currPtsDevName[32];
573 SharedData::getRealPtyName(path, currPtsDevName,
574 sizeof(currPtsDevName));
575 strcpy(*newpath, currPtsDevName);
576 } else {
577 *newpath = (char*) path;
578 }
579 }
580
581 extern "C" int __xstat(int vers, const char *path, struct stat *buf)
582 {
583 char tmpbuf [ PATH_MAX ] = {0} ;
584 char *newpath = tmpbuf;
585 DMTCP_PLUGIN_DISABLE_CKPT();
586 updateStatPath(path, &newpath);
587 int retval = _real_xstat(vers, newpath, buf);
588 DMTCP_PLUGIN_ENABLE_CKPT();
589 return retval;
590 }
591
592 extern "C" int __xstat64(int vers, const char *path, struct stat64 *buf)
593 {
594 char tmpbuf [ PATH_MAX ] = {0};
595 char *newpath = tmpbuf;
596 DMTCP_PLUGIN_DISABLE_CKPT();
597 updateStatPath(path, &newpath);
598 int retval = _real_xstat64(vers, newpath, buf);
599 DMTCP_PLUGIN_ENABLE_CKPT();
600 return retval;
601 }
602
603 #if 0
604 extern "C" int __fxstat(int vers, int fd, struct stat *buf)
605 {
606 DMTCP_PLUGIN_DISABLE_CKPT();
607 int retval = _real_fxstat(vers, fd, buf);
608 DMTCP_PLUGIN_ENABLE_CKPT();
609 return retval;
610 }
611
612 extern "C" int __fxstat64(int vers, int fd, struct stat64 *buf)
613 {
614 DMTCP_PLUGIN_DISABLE_CKPT();
615 int retval = _real_fxstat64(vers, fd, buf);
616 DMTCP_PLUGIN_ENABLE_CKPT();
617 return retval;
618 }
619 #endif
620
621 extern "C" int __lxstat(int vers, const char *path, struct stat *buf)
622 {
623 char tmpbuf [ PATH_MAX ] = {0} ;
624 char *newpath = tmpbuf;
625 DMTCP_PLUGIN_DISABLE_CKPT();
626 updateStatPath(path, &newpath);
627 int retval = _real_lxstat(vers, newpath, buf);
628 DMTCP_PLUGIN_ENABLE_CKPT();
629 return retval;
630 }
631
632 extern "C" int __lxstat64(int vers, const char *path, struct stat64 *buf)
633 {
634 char tmpbuf [ PATH_MAX ] = {0} ;
635 char *newpath = tmpbuf;
636 DMTCP_PLUGIN_DISABLE_CKPT();
637 updateStatPath(path, &newpath);
638 int retval = _real_lxstat64(vers, newpath, buf);
639 DMTCP_PLUGIN_ENABLE_CKPT();
640 return retval;
641 }
642
643 //FIXME: Add wrapper for readlinkat
644 // NOTE: If you see a compiler error: "declaration of C function ... conflicts
645 // with ... unistd.h", then consider changing ssize_t to int
646 // A user has reported this was needed for Linux SLES10.
647 extern "C" ssize_t readlink(const char *path, char *buf, size_t bufsiz)
648 {
649 char tmpbuf [ PATH_MAX ] = {0} ;
650 char *newpath = tmpbuf;
651 DMTCP_PLUGIN_DISABLE_CKPT();
652 ssize_t retval;
653 if (path != NULL && strcmp(path, "/proc/self/exe") == 0) {
654 const char *procSelfExe = dmtcp_get_executable_path();
655 strncpy(buf, procSelfExe, bufsiz);
656 retval = bufsiz > strlen(procSelfExe) ? strlen(procSelfExe) : bufsiz;
657 } else {
658 updateStatPath(path, &newpath);
659 retval = _real_readlink(newpath, buf, bufsiz);
660 }
661 DMTCP_PLUGIN_ENABLE_CKPT();
662 return retval;
663 }
664
665 extern "C" ssize_t __readlink_chk(const char *path, char *buf,
666 size_t bufsiz, size_t buflen)
667 {
668 return readlink(path, buf, bufsiz);
669 }
670
671 extern "C" int fcntl(int fd, int cmd, ...)
672 {
673 void *arg = NULL;
674 va_list ap;
675 va_start(ap, cmd);
676 arg = va_arg(ap, void *);
677 va_end(ap);
678
679 DMTCP_PLUGIN_DISABLE_CKPT();
680
681 int res = _real_fcntl(fd, cmd, arg);
682 if (res != -1 &&
683 #if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,24)
684 (cmd == F_DUPFD || cmd == F_DUPFD_CLOEXEC) &&
685 #else
686 (cmd == F_DUPFD) &&
687 #endif
688 dmtcp_is_running_state()) {
689 FileConnList::instance().processDup(fd, res);
690 }
691
692 DMTCP_PLUGIN_ENABLE_CKPT();
693 return res;
694 }
695
696 extern "C" char *realpath(const char *path, char *resolved_path)
697 {
698 char *ret;
699 if (Util::strStartsWith(path, "/dev/pts")) {
700 JASSERT(strlen(path) < PATH_MAX);
701 if (resolved_path == NULL) {
702 ret = (char*) malloc(strlen(path) + 1);
703 } else {
704 ret = resolved_path;
705 }
706 strcpy(ret, path);
707 } else {
708 ret = _real_realpath(path, resolved_path);
709 }
710 return ret;
711 }
712
713 extern "C" char *__realpath(const char *path, char *resolved_path)
714 {
715 return realpath(path, resolved_path);
716 }
717
718 extern "C" char *__realpath_chk(const char *path, char *resolved_path,
719 size_t resolved_len)
720 {
721 return realpath(path, resolved_path);
722 }
723
724 extern "C" char *canonicalize_file_name(const char *path)
725 {
726 return realpath(path, NULL);
727 }
728
729 extern "C" int access(const char *path, int mode)
730 {
731 if (Util::strStartsWith(path, "/dev/pts")) {
732 char currPtsDevName[32];
733 DMTCP_PLUGIN_DISABLE_CKPT();
734 SharedData::getRealPtyName(path, currPtsDevName, sizeof(currPtsDevName));
735 int ret = _real_access(currPtsDevName, mode);
736 DMTCP_PLUGIN_ENABLE_CKPT();
737 return ret;
738 }
739 return _real_access(path, mode);
740 }
741
742 #if 0
743 // TODO: ioctl must use virtualized pids for request = TIOCGPGRP / TIOCSPGRP
744 // These are synonyms for POSIX standard tcgetpgrp / tcsetpgrp
745 extern "C" {
746 int send_sigwinch = 0;
747 }
748
749 extern "C" int ioctl(int d, unsigned long int request, ...)
750 {
751 va_list ap;
752 int retval;
753
754 if (send_sigwinch && request == TIOCGWINSZ) {
755 send_sigwinch = 0;
756 va_list local_ap;
757 va_copy(local_ap, ap);
758 va_start(local_ap, request);
759 struct winsize * win = va_arg(local_ap, struct winsize *);
760 va_end(local_ap);
761 retval = _real_ioctl(d, request, win); // This fills in win
762 win->ws_col--; // Lie to application, and force it to resize window,
763 // reset any scroll regions, etc.
764 kill(getpid(), SIGWINCH); // Tell application to look up true winsize
765 // and resize again.
766 } else {
767 void * arg;
768 va_start(ap, request);
769 arg = va_arg(ap, void *);
770 va_end(ap);
771 retval = _real_ioctl(d, request, arg);
772 }
773 return retval;
774 }
775 #endif