Cygwin: strptime: add release note
[newlib-cygwin.git] / winsup / cygwin / fhandler / virtual.cc
blob21ff4f35ead199fb67ddc96259955ec58aaea7a6
1 /* fhandler_virtual.cc: base fhandler class for virtual filesystems
3 This file is part of Cygwin.
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. */
9 #include "winsup.h"
10 #include <cygwin/acl.h>
11 #include <sys/statvfs.h>
12 #include "cygerrno.h"
13 #include "path.h"
14 #include "fhandler.h"
15 #include "dtable.h"
16 #include "cygheap.h"
17 #include "sync.h"
18 #include "child_info.h"
20 #include <dirent.h>
22 fhandler_virtual::fhandler_virtual ():
23 fhandler_base (), filebuf (NULL), fileid (-1)
27 fhandler_virtual::~fhandler_virtual ()
29 if (filebuf)
31 cfree (filebuf);
32 filebuf = NULL;
36 void
37 fhandler_virtual::fixup_after_exec ()
41 DIR *
42 fhandler_virtual::opendir (int fd)
44 DIR *dir;
45 DIR *res = NULL;
46 size_t len;
48 if (!virt_ftype_isdir (exists ()))
49 set_errno (ENOTDIR);
50 else if ((len = strlen (get_name ())) > PATH_MAX - 3)
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)
56 free (dir);
57 set_errno (ENOMEM);
59 else if ((dir->__d_dirent =
60 (struct dirent *) malloc (sizeof (struct dirent))) == NULL)
62 free (dir->__d_dirname);
63 free (dir);
64 set_errno (ENOMEM);
66 else
68 strcpy (dir->__d_dirname, get_name ());
69 dir->__d_dirent->__d_version = __DIRENT_VERSION;
70 dir->__d_cookie = __DIRENT_COOKIE;
71 dir->__handle = INVALID_HANDLE_VALUE;
72 dir->__d_position = 0;
73 dir->__flags = 0;
75 if (fd >= 0)
77 dir->__d_fd = fd;
78 dir->__fh = this;
79 res = dir;
81 else
83 cygheap_fdnew cfd;
84 if (cfd >= 0 && open (O_RDONLY, 0))
86 cfd = this;
87 dir->__d_fd = cfd;
88 dir->__fh = this;
89 res = dir;
92 close_on_exec (true);
95 syscall_printf ("%p = opendir (%s)", res, get_name ());
96 return res;
99 long
100 fhandler_virtual::telldir (DIR * dir)
102 return dir->__d_position;
105 void
106 fhandler_virtual::seekdir (DIR * dir, long loc)
108 dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot;
109 dir->__d_position = loc;
112 void
113 fhandler_virtual::rewinddir (DIR * dir)
115 dir->__d_position = 0;
116 dir->__flags |= dirent_saw_dot | dirent_saw_dot_dot;
120 fhandler_virtual::closedir (DIR * dir)
122 return 0;
125 off_t
126 fhandler_virtual::lseek (off_t offset, int whence)
129 * On Linux, when you lseek within a /proc file,
130 * the contents of the file are updated.
132 if (!fill_filebuf ())
133 return (off_t) -1;
134 switch (whence)
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);
147 return (off_t) -1;
149 return position;
153 fhandler_virtual::dup (fhandler_base * child, int flags)
155 int ret = fhandler_base::dup (child, flags);
157 if (!ret)
159 fhandler_virtual *fhproc_child = (fhandler_virtual *) child;
160 fhproc_child->filebuf = (char *) cmalloc_abort (HEAP_BUF, filesize);
161 memcpy (fhproc_child->filebuf, filebuf, filesize);
163 return ret;
167 fhandler_virtual::close ()
169 if (!have_execed)
171 if (filebuf)
173 cfree (filebuf);
174 filebuf = NULL;
177 return 0;
180 void
181 fhandler_virtual::read (void *ptr, size_t& len)
183 if (len == 0)
184 return;
185 if (diropen)
187 set_errno (EISDIR);
188 len = (size_t) -1;
189 return;
191 if (!filebuf)
193 len = (size_t) 0;
194 return;
196 if ((ssize_t) len > filesize - position)
197 len = (size_t) (filesize - position);
198 if ((ssize_t) len < 0)
199 len = 0;
200 else
201 memcpy (ptr, filebuf + position, len);
202 position += len;
205 ssize_t
206 fhandler_virtual::write (const void *ptr, size_t len)
208 set_errno (EACCES);
209 return -1;
212 /* low-level open for all proc files */
214 fhandler_virtual::open (int flags, mode_t mode)
216 rbinary (true);
217 wbinary (true);
219 set_flags ((flags & ~O_TEXT) | O_BINARY);
221 return 1;
224 virtual_ftype_t
225 fhandler_virtual::exists ()
227 return virt_none;
230 bool
231 fhandler_virtual::fill_filebuf ()
233 return true;
237 fhandler_virtual::fchmod (mode_t mode)
239 /* Same as on Linux. */
240 set_errno (EPERM);
241 return -1;
245 fhandler_virtual::fchown (uid_t uid, gid_t gid)
247 /* Same as on Linux. */
248 set_errno (EPERM);
249 return -1;
253 fhandler_virtual::facl (int cmd, int nentries, aclent_t *aclbufp)
255 int res = fhandler_base::facl (cmd, nentries, aclbufp);
256 if (res >= 0 && cmd == GETACL)
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);
262 return res;
266 fhandler_virtual::fstatvfs (struct statvfs *sfs)
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;
272 sfs->f_flag = ST_RDONLY;
273 sfs->f_namemax = NAME_MAX;
274 return 0;