]>
Commit | Line | Data |
---|---|---|
c477dccf CF |
1 | /* fhandler_virtual.cc: base fhandler class for virtual filesystems |
2 | ||
c477dccf CF |
3 | This file is part of Cygwin. |
4 | ||
5 | This software is a copyrighted work licensed under the terms of the | |
6 | Cygwin license. Please consult the file "CYGWIN_LICENSE" for | |
7 | details. */ | |
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 | 22 | fhandler_virtual::fhandler_virtual (): |
38f50ae4 | 23 | fhandler_base (), filebuf (NULL), fileid (-1) |
c477dccf CF |
24 | { |
25 | } | |
26 | ||
27 | fhandler_virtual::~fhandler_virtual () | |
28 | { | |
29 | if (filebuf) | |
14c4d65e CF |
30 | { |
31 | cfree (filebuf); | |
32 | filebuf = NULL; | |
33 | } | |
c477dccf CF |
34 | } |
35 | ||
831d6fa5 | 36 | void |
52806019 | 37 | fhandler_virtual::fixup_after_exec () |
831d6fa5 | 38 | { |
831d6fa5 CF |
39 | } |
40 | ||
c477dccf | 41 | DIR * |
40570a82 | 42 | fhandler_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 |
99 | long |
100 | fhandler_virtual::telldir (DIR * dir) | |
c477dccf CF |
101 | { |
102 | return dir->__d_position; | |
103 | } | |
104 | ||
105 | void | |
c492992f | 106 | fhandler_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 | ||
112 | void | |
113 | fhandler_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 | ||
119 | int | |
120 | fhandler_virtual::closedir (DIR * dir) | |
121 | { | |
122 | return 0; | |
123 | } | |
124 | ||
61522196 CV |
125 | off_t |
126 | fhandler_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 | ||
152 | int | |
23771fa1 | 153 | fhandler_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 | ||
166 | int | |
167 | fhandler_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 | 180 | void __reg3 |
8bce0d72 | 181 | fhandler_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 | 205 | ssize_t __stdcall |
c477dccf CF |
206 | fhandler_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 */ | |
213 | int | |
7ac61736 | 214 | fhandler_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 | 224 | virtual_ftype_t |
fc240f58 | 225 | fhandler_virtual::exists () |
c477dccf | 226 | { |
43f65cdd | 227 | return virt_none; |
c477dccf | 228 | } |
9ba913a5 | 229 | |
74fcdaec | 230 | bool |
9ba913a5 CF |
231 | fhandler_virtual::fill_filebuf () |
232 | { | |
74fcdaec | 233 | return true; |
9ba913a5 | 234 | } |
854c8700 CV |
235 | |
236 | int | |
237 | fhandler_virtual::fchmod (mode_t mode) | |
238 | { | |
239 | /* Same as on Linux. */ | |
240 | set_errno (EPERM); | |
241 | return -1; | |
242 | } | |
ddf9c4a7 CV |
243 | |
244 | int | |
61522196 | 245 | fhandler_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 | |
252 | int | |
61522196 | 253 | fhandler_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 | 265 | int __reg2 |
3323df7e CV |
266 | fhandler_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 | } |