]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/fhandler_virtual.cc
Cygwin: drop internal O_NOSYMLINK and O_DIROPEN flags
[newlib-cygwin.git] / winsup / cygwin / fhandler_virtual.cc
CommitLineData
c477dccf
CF
1/* fhandler_virtual.cc: base fhandler class for virtual filesystems
2
c477dccf
CF
3This file is part of Cygwin.
4
5This software is a copyrighted work licensed under the terms of the
6Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7details. */
8
9#include "winsup.h"
9ddf0639 10#include <cygwin/acl.h>
3323df7e 11#include <sys/statvfs.h>
c477dccf 12#include "cygerrno.h"
c477dccf 13#include "path.h"
7ac61736 14#include "fhandler.h"
c477dccf 15#include "dtable.h"
8761c1dc 16#include "cygheap.h"
56a19715
CF
17#include "sync.h"
18#include "child_info.h"
c477dccf 19
c477dccf
CF
20#include <dirent.h>
21
7ac61736 22fhandler_virtual::fhandler_virtual ():
38f50ae4 23 fhandler_base (), filebuf (NULL), fileid (-1)
c477dccf
CF
24{
25}
26
27fhandler_virtual::~fhandler_virtual ()
28{
29 if (filebuf)
14c4d65e
CF
30 {
31 cfree (filebuf);
32 filebuf = NULL;
33 }
c477dccf
CF
34}
35
831d6fa5 36void
52806019 37fhandler_virtual::fixup_after_exec ()
831d6fa5 38{
831d6fa5
CF
39}
40
c477dccf 41DIR *
40570a82 42fhandler_virtual::opendir (int fd)
c477dccf
CF
43{
44 DIR *dir;
45 DIR *res = NULL;
46 size_t len;
47
dec444be 48 if (!virt_ftype_isdir (exists ()))
c477dccf 49 set_errno (ENOTDIR);
5224a7bb 50 else if ((len = strlen (get_name ())) > PATH_MAX - 3)
c477dccf
CF
51 set_errno (ENAMETOOLONG);
52 else if ((dir = (DIR *) malloc (sizeof (DIR))) == NULL)
53 set_errno (ENOMEM);
54 else if ((dir->__d_dirname = (char *) malloc (len + 3)) == NULL)
55 {
56 free (dir);
57 set_errno (ENOMEM);
58 }
59 else if ((dir->__d_dirent =
60 (struct dirent *) malloc (sizeof (struct dirent))) == NULL)
61 {
fe222f22 62 free (dir->__d_dirname);
c477dccf
CF
63 free (dir);
64 set_errno (ENOMEM);
65 }
66 else
67 {
335c87f9 68 strcpy (dir->__d_dirname, get_name ());
868fb2ff 69 dir->__d_dirent->__d_version = __DIRENT_VERSION;
40570a82
CV
70 dir->__d_cookie = __DIRENT_COOKIE;
71 dir->__handle = INVALID_HANDLE_VALUE;
72 dir->__d_position = 0;
73 dir->__flags = 0;
74
518f5d49 75 if (fd >= 0)
8581e92c 76 {
868fb2ff 77 dir->__d_fd = fd;
0c7b5572 78 dir->__fh = this;
518f5d49 79 res = dir;
40570a82
CV
80 }
81 else
8581e92c 82 {
40570a82 83 cygheap_fdnew cfd;
5b312b47 84 if (cfd >= 0 && open (O_RDONLY, 0))
40570a82
CV
85 {
86 cfd = this;
40570a82
CV
87 dir->__d_fd = cfd;
88 dir->__fh = this;
89 res = dir;
90 }
518f5d49 91 }
281bd334 92 close_on_exec (true);
c477dccf
CF
93 }
94
95 syscall_printf ("%p = opendir (%s)", res, get_name ());
96 return res;
97}
98
c492992f
CV
99long
100fhandler_virtual::telldir (DIR * dir)
c477dccf
CF
101{
102 return dir->__d_position;
103}
104
105void
c492992f 106fhandler_virtual::seekdir (DIR * dir, long loc)
c477dccf 107{
2693c1ac 108 dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot;
c477dccf 109 dir->__d_position = loc;
c477dccf
CF
110}
111
112void
113fhandler_virtual::rewinddir (DIR * dir)
114{
115 dir->__d_position = 0;
2693c1ac 116 dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot;
c477dccf
CF
117}
118
119int
120fhandler_virtual::closedir (DIR * dir)
121{
122 return 0;
123}
124
61522196
CV
125off_t
126fhandler_virtual::lseek (off_t offset, int whence)
c477dccf 127{
9ba913a5
CF
128 /*
129 * On Linux, when you lseek within a /proc file,
130 * the contents of the file are updated.
131 */
74fcdaec 132 if (!fill_filebuf ())
61522196 133 return (off_t) -1;
c477dccf
CF
134 switch (whence)
135 {
136 case SEEK_SET:
137 position = offset;
138 break;
139 case SEEK_CUR:
140 position += offset;
141 break;
142 case SEEK_END:
143 position = filesize + offset;
144 break;
145 default:
146 set_errno (EINVAL);
61522196 147 return (off_t) -1;
c477dccf
CF
148 }
149 return position;
150}
151
152int
23771fa1 153fhandler_virtual::dup (fhandler_base * child, int flags)
c477dccf 154{
23771fa1 155 int ret = fhandler_base::dup (child, flags);
8761c1dc
CF
156
157 if (!ret)
158 {
159 fhandler_virtual *fhproc_child = (fhandler_virtual *) child;
ee4388c4 160 fhproc_child->filebuf = (char *) cmalloc_abort (HEAP_BUF, filesize);
8761c1dc 161 memcpy (fhproc_child->filebuf, filebuf, filesize);
8761c1dc
CF
162 }
163 return ret;
c477dccf
CF
164}
165
166int
167fhandler_virtual::close ()
168{
56a19715 169 if (!have_execed)
2f9ae2ed 170 {
b56c466b
CF
171 if (filebuf)
172 {
173 cfree (filebuf);
174 filebuf = NULL;
175 }
2f9ae2ed 176 }
c477dccf
CF
177 return 0;
178}
179
1f36328e 180void __reg3
8bce0d72 181fhandler_virtual::read (void *ptr, size_t& len)
c477dccf
CF
182{
183 if (len == 0)
8bce0d72 184 return;
8d0ff076 185 if (diropen)
c477dccf
CF
186 {
187 set_errno (EISDIR);
6cce721b 188 len = (size_t) -1;
8bce0d72 189 return;
c477dccf
CF
190 }
191 if (!filebuf)
8bce0d72 192 {
6cce721b 193 len = (size_t) 0;
8bce0d72
CF
194 return;
195 }
196 if ((ssize_t) len > filesize - position)
6cce721b 197 len = (size_t) (filesize - position);
8bce0d72 198 if ((ssize_t) len < 0)
6cce721b 199 len = 0;
c477dccf 200 else
8bce0d72
CF
201 memcpy (ptr, filebuf + position, len);
202 position += len;
c477dccf
CF
203}
204
43c23d4b 205ssize_t __stdcall
c477dccf
CF
206fhandler_virtual::write (const void *ptr, size_t len)
207{
8761c1dc 208 set_errno (EACCES);
c477dccf
CF
209 return -1;
210}
211
212/* low-level open for all proc files */
213int
7ac61736 214fhandler_virtual::open (int flags, mode_t mode)
c477dccf 215{
56551a9b
CV
216 rbinary (true);
217 wbinary (true);
c477dccf 218
1bc9effd 219 set_flags ((flags & ~O_TEXT) | O_BINARY);
c477dccf
CF
220
221 return 1;
222}
223
43f65cdd 224virtual_ftype_t
fc240f58 225fhandler_virtual::exists ()
c477dccf 226{
43f65cdd 227 return virt_none;
c477dccf 228}
9ba913a5 229
74fcdaec 230bool
9ba913a5
CF
231fhandler_virtual::fill_filebuf ()
232{
74fcdaec 233 return true;
9ba913a5 234}
854c8700
CV
235
236int
237fhandler_virtual::fchmod (mode_t mode)
238{
239 /* Same as on Linux. */
240 set_errno (EPERM);
241 return -1;
242}
ddf9c4a7
CV
243
244int
61522196 245fhandler_virtual::fchown (uid_t uid, gid_t gid)
ddf9c4a7
CV
246{
247 /* Same as on Linux. */
248 set_errno (EPERM);
249 return -1;
250}
e3d1d515
CV
251
252int
61522196 253fhandler_virtual::facl (int cmd, int nentries, aclent_t *aclbufp)
e3d1d515 254{
aafdf30f
CV
255 int res = fhandler_base::facl (cmd, nentries, aclbufp);
256 if (res >= 0 && cmd == GETACL)
257 {
258 aclbufp[0].a_perm = (S_IRUSR | (pc.isdir () ? S_IXUSR : 0)) >> 6;
259 aclbufp[1].a_perm = (S_IRGRP | (pc.isdir () ? S_IXGRP : 0)) >> 3;
260 aclbufp[2].a_perm = S_IROTH | (pc.isdir () ? S_IXOTH : 0);
261 }
262 return res;
e3d1d515 263}
3323df7e 264
1f36328e 265int __reg2
3323df7e
CV
266fhandler_virtual::fstatvfs (struct statvfs *sfs)
267{
268 /* Virtual file system. Just return an empty buffer with a few values
269 set to something useful. Just as on Linux. */
270 memset (sfs, 0, sizeof (*sfs));
271 sfs->f_bsize = sfs->f_frsize = 4096;
5b312b47 272 sfs->f_flag = ST_RDONLY;
3323df7e
CV
273 sfs->f_namemax = NAME_MAX;
274 return 0;
275}
This page took 0.423981 seconds and 5 git commands to generate.