chromecast: rework demux pacing
[vlc.git] / src / os2 / filesystem.c
blobbbb4ab346bd6821e65e4bed452518ff62456a583
1 /*****************************************************************************
2 * filesystem.c: OS/2 file system helpers
3 *****************************************************************************
4 * Copyright (C) 2005-2006 VLC authors and VideoLAN
5 * Copyright © 2005-2008 Rémi Denis-Courmont
6 * Copyright (C) 2012 KO Myung-Hun
8 * Authors: Rémi Denis-Courmont <rem # videolan.org>
9 * KO Myung-Hun <komh@chollian.net>
11 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU Lesser General Public License as published by
13 * the Free Software Foundation; either version 2.1 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public License
22 * along with this program; if not, write to the Free Software Foundation,
23 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24 *****************************************************************************/
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
30 #include <assert.h>
32 #include <stdio.h>
33 #include <errno.h>
35 #include <sys/types.h>
36 #include <unistd.h>
37 #include <io.h>
38 #include <fcntl.h>
39 #include <sys/stat.h>
40 #include <dirent.h>
41 #include <sys/socket.h>
42 #include <signal.h>
44 #include <vlc_common.h>
45 #include <vlc_charset.h>
46 #include <vlc_fs.h>
47 #include <vlc_network.h>
48 #include "libvlc.h" /* vlc_mkdir */
50 int vlc_open (const char *filename, int flags, ...)
52 unsigned int mode = 0;
53 va_list ap;
55 va_start (ap, flags);
56 if (flags & O_CREAT)
57 mode = va_arg (ap, unsigned int);
58 va_end (ap);
60 const char *local_name = ToLocaleDup (filename);
62 if (local_name == NULL)
64 errno = ENOENT;
65 return -1;
68 int fd = open (local_name, flags, mode);
69 if (fd != -1)
70 fcntl (fd, F_SETFD, FD_CLOEXEC);
72 free (local_name);
73 return fd;
76 int vlc_openat (int dir, const char *filename, int flags, ...)
78 errno = ENOSYS;
80 return -1;
83 int vlc_memfd (void)
85 errno = ENOSYS;
86 return -1;
89 int vlc_close (int fd)
91 return close (fd);
94 int vlc_mkdir (const char *dirname, mode_t mode)
96 char *locname = ToLocaleDup (dirname);
97 if (unlikely(locname == NULL))
99 errno = ENOENT;
100 return -1;
103 int res = mkdir (locname, mode);
104 free (locname);
105 return res;
108 DIR *vlc_opendir (const char *dirname)
110 const char *locname = ToLocaleDup (dirname);
111 if (unlikely(locname == NULL))
113 errno = ENOENT;
114 return NULL;
117 DIR *dir = opendir (locname);
119 free (locname);
121 return dir;
124 const char *vlc_readdir(DIR *dir)
126 /* Beware that readdir_r() assumes <buf> is large enough to hold the result
127 * dirent including the file name. A buffer overflow could occur otherwise.
128 * In particular, pathconf() and _POSIX_NAME_MAX cannot be used here. */
129 struct dirent *ent;
130 char *path = NULL;
132 /* In the implementation of Innotek LIBC, aka kLIBC on OS/2,
133 * fpathconf (_PC_NAME_MAX) is broken, and errno is set to EBADF.
134 * Moreover, d_name is not the last member of struct dirent.
135 * So just allocate as many as the size of struct dirent. */
136 #if 1
137 long len = sizeof (struct dirent);
138 #else
139 long len = fpathconf (dirfd (dir), _PC_NAME_MAX);
140 len += offsetof (struct dirent, d_name) + 1;
141 #endif
143 struct dirent *buf = malloc (len);
144 if (unlikely(buf == NULL))
145 return NULL;
147 int val = readdir_r (dir, buf, &ent);
148 if (val != 0)
149 errno = val;
150 else if (ent != NULL)
151 path = FromCharset ("", ent->d_name, strlen(ent->d_name));
152 free (buf);
153 return path;
156 static int vlc_statEx (const char *filename, struct stat *buf, bool deref)
158 const char *local_name = ToLocaleDup (filename);
159 if (unlikely(local_name == NULL))
161 errno = ENOENT;
162 return -1;
165 int res = deref ? stat (local_name, buf)
166 : lstat (local_name, buf);
167 free (local_name);
168 return res;
171 int vlc_stat (const char *filename, struct stat *buf)
173 return vlc_statEx (filename, buf, true);
176 int vlc_lstat (const char *filename, struct stat *buf)
178 return vlc_statEx (filename, buf, false);
181 int vlc_unlink (const char *filename)
183 const char *local_name = ToLocaleDup (filename);
184 if (unlikely(local_name == NULL))
186 errno = ENOENT;
187 return -1;
190 int ret = unlink (local_name);
191 free (local_name);
192 return ret;
195 int vlc_rename (const char *oldpath, const char *newpath)
197 const char *lo = ToLocaleDup (oldpath);
198 if (lo == NULL)
199 goto error;
201 const char *ln = ToLocaleDup (newpath);
202 if (ln == NULL)
204 free (lo);
205 error:
206 errno = ENOENT;
207 return -1;
210 int ret = rename (lo, ln);
211 free (lo);
212 free (ln);
213 return ret;
216 char *vlc_getcwd (void)
218 /* Try $PWD */
219 const char *pwd = getenv ("PWD");
220 if (pwd != NULL)
222 struct stat s1, s2;
223 /* Make sure $PWD is correct */
224 if (stat (pwd, &s1) == 0 && stat (".", &s2) == 0
225 && s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino)
226 return ToLocaleDup (pwd);
229 /* Otherwise iterate getcwd() until the buffer is big enough */
230 long path_max = pathconf (".", _PC_PATH_MAX);
231 size_t size = (path_max == -1 || path_max > 4096) ? 4096 : path_max;
233 for (;; size *= 2)
235 char *buf = malloc (size);
236 if (unlikely(buf == NULL))
237 break;
239 if (getcwd (buf, size) != NULL)
241 char *ret = ToLocaleDup (buf);
242 free (buf);
243 return ret; /* success */
245 free (buf);
247 if (errno != ERANGE)
248 break;
250 return NULL;
253 int vlc_dup (int oldfd)
255 int newfd;
257 newfd = dup (oldfd);
258 if (likely(newfd != -1))
259 fcntl (newfd, F_SETFD, FD_CLOEXEC);
261 return newfd;
264 int vlc_pipe (int fds[2])
266 if (vlc_socketpair (AF_LOCAL, SOCK_STREAM, 0, fds, false))
267 return -1;
269 shutdown (fds[0], SHUT_WR);
270 shutdown (fds[1], SHUT_RD);
272 setmode (fds[0], O_BINARY);
273 setmode (fds[1], O_BINARY);
275 return 0;
278 ssize_t vlc_write(int fd, const void *buf, size_t len)
280 struct iovec iov = { .iov_base = (void *)buf, .iov_len = len };
282 return vlc_writev(fd, &iov, 1);
285 ssize_t vlc_writev(int fd, const struct iovec *iov, int count)
287 sigset_t set, oset;
289 sigemptyset(&set);
290 sigaddset(&set, SIGPIPE);
291 pthread_sigmask(SIG_BLOCK, &set, &oset);
293 ssize_t val = writev(fd, iov, count);
294 if (val < 0 && errno == EPIPE)
296 siginfo_t info;
297 struct timespec ts = { 0, 0 };
299 while (sigtimedwait(&set, &info, &ts) >= 0 || errno != EAGAIN);
302 if (!sigismember(&oset, SIGPIPE)) /* Restore the signal mask if changed */
303 pthread_sigmask(SIG_SETMASK, &oset, NULL);
305 return val;
308 static void vlc_socket_setup(int fd, bool nonblock)
310 fcntl(fd, F_SETFD, FD_CLOEXEC);
312 if (nonblock)
313 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
316 int vlc_socket (int pf, int type, int proto, bool nonblock)
318 int fd = socket(pf, type, proto);
319 if (fd != -1)
320 vlc_socket_setup(fd, nonblock);
321 return fd;
324 int vlc_socketpair(int pf, int type, int proto, int fds[2], bool nonblock)
326 if (socketpair(pf, type, proto, fds))
327 return -1;
329 vlc_socket_setup(fds[0], nonblock);
330 vlc_socket_setup(fds[1], nonblock);
331 return 0;
334 int vlc_accept (int lfd, struct sockaddr *addr, socklen_t *alen, bool nonblock)
338 int fd = accept (lfd, addr, alen);
339 if (fd != -1)
341 fcntl (fd, F_SETFD, FD_CLOEXEC);
342 if (nonblock)
343 fcntl (fd, F_SETFL, fcntl (fd, F_GETFL, 0) | O_NONBLOCK);
344 return fd;
347 while (errno == EINTR);
349 return -1;