aboutsummaryrefslogtreecommitdiffstats
path: root/ports/linux/guts/openat.c
blob: a3637c8020d882c21bae81dd24e7977788471e09 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
/* 
 * Copyright (c) 2008-2010, 2013 Wind River Systems; see
 * guts/COPYRIGHT for information.
 *
 * static int
 * wrap_openat(int dirfd, const char *path, int flags, ...mode_t mode) {
 *	int rc = -1;
 */
	struct stat64 buf;
	int existed = 1;
	int save_errno;

	/* mask out mode bits appropriately */
	mode = mode & ~pseudo_umask;

#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
	if (dirfd != AT_FDCWD) {
		errno = ENOSYS;
		return -1;
	}
#endif

#ifdef PSEUDO_FORCE_ASYNCH
        /* Yes, I'm aware that every Linux system I've seen has
         * DSYNC and RSYNC being the same value as SYNC.
         */

        flags &= ~(O_SYNC
#ifdef O_DIRECT
                | O_DIRECT
#endif
#ifdef O_DSYNC
                | O_DSYNC
#endif
#ifdef O_RSYNC
                | O_RSYNC
#endif
        );
#endif

#ifdef O_TMPFILE
	/* don't handle O_CREAT the same way if O_TMPFILE exists
	 * and is set.
	 */
	if (flags & O_TMPFILE) {
		existed = 0;
	} else
#endif
	/* if a creation has been requested, check whether file exists */
	/* note "else" in #ifdef O_TMPFILE above */
	if (flags & O_CREAT) {
		save_errno = errno;
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
		rc = real___xstat64(_STAT_VER, path, &buf);
#else
		rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0);
#endif
		existed = (rc != -1);
		if (!existed)
			pseudo_debug(PDBGF_FILE, "openat_creat: %s -> 0%o\n", path, mode);
		errno = save_errno;
	}

	/* because we are not actually root, secretly mask in 0600 to the
	 * underlying mode.  The ", 0" is because the only time mode matters
	 * is if a file is going to be created, in which case it's
	 * not a directory.
	 */
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
	rc = real_open(path, flags, PSEUDO_FS_MODE(mode, 0));
#else
	rc = real_openat(dirfd, path, flags, PSEUDO_FS_MODE(mode, 0));
#endif

	if (rc != -1) {
		save_errno = errno;
		int stat_rc;
#ifdef O_TMPFILE
		/* in O_TMPFILE case, nothing gets put in the
		 * database, because there's no directory entries for
		 * the file yet.
		 */
		if (flags & O_TMPFILE) {
			real_fchmod(rc, PSEUDO_FS_MODE(mode, 0));
			errno = save_errno;
			return rc;
		}
#endif
#ifdef PSEUDO_NO_REAL_AT_FUNCTIONS
		stat_rc = real___xstat64(_STAT_VER, path, &buf);
#else
		stat_rc = real___fxstatat64(_STAT_VER, dirfd, path, &buf, 0);
#endif

		if (stat_rc != -1) {
			buf.st_mode = PSEUDO_DB_MODE(buf.st_mode, mode);
			if (!existed) {
				real_fchmod(rc, PSEUDO_FS_MODE(mode, 0));
				// file has no path, but has been created
				pseudo_client_op(OP_CREAT, 0, -1, dirfd, path, &buf);
			}
				pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, path, &buf);
		} else {
			pseudo_debug(PDBGF_FILE, "openat (fd %d, path %d/%s, flags %d) succeeded, but stat failed (%s).\n",
				rc, dirfd, path, flags, strerror(errno));
			pseudo_client_op(OP_OPEN, PSEUDO_ACCESS(flags), rc, dirfd, path, 0);
		}
		errno = save_errno;
	}

/*	return rc;
 * }
 */