src: fix fourcc_gen build on OS/2
[vlc.git] / src / os2 / filesystem.c
blob5017abe689615985ffceff8c22a7b84d44fa2700
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 "libvlc.h" /* vlc_mkdir */
49 /**
50 * Opens a system file handle.
52 * @param filename file path to open (with UTF-8 encoding)
53 * @param flags open() flags, see the C library open() documentation
54 * @return a file handle on success, -1 on error (see errno).
55 * @note Contrary to standard open(), this function returns file handles
56 * with the close-on-exec flag enabled.
58 int vlc_open (const char *filename, int flags, ...)
60 unsigned int mode = 0;
61 va_list ap;
63 va_start (ap, flags);
64 if (flags & O_CREAT)
65 mode = va_arg (ap, unsigned int);
66 va_end (ap);
68 const char *local_name = ToLocaleDup (filename);
70 if (local_name == NULL)
72 errno = ENOENT;
73 return -1;
76 int fd = open (local_name, flags, mode);
77 if (fd != -1)
78 fcntl (fd, F_SETFD, FD_CLOEXEC);
80 free (local_name);
81 return fd;
84 /**
85 * Opens a system file handle relative to an existing directory handle.
87 * @param dir directory file descriptor
88 * @param filename file path to open (with UTF-8 encoding)
89 * @param flags open() flags, see the C library open() documentation
90 * @return a file handle on success, -1 on error (see errno).
91 * @note Contrary to standard open(), this function returns file handles
92 * with the close-on-exec flag enabled.
94 int vlc_openat (int dir, const char *filename, int flags, ...)
96 errno = ENOSYS;
98 return -1;
103 * Creates a directory using UTF-8 paths.
105 * @param dirname a UTF-8 string with the name of the directory that you
106 * want to create.
107 * @param mode directory permissions
108 * @return 0 on success, -1 on error (see errno).
110 int vlc_mkdir (const char *dirname, mode_t mode)
112 char *locname = ToLocaleDup (dirname);
113 if (unlikely(locname == NULL))
115 errno = ENOENT;
116 return -1;
119 int res = mkdir (locname, mode);
120 free (locname);
121 return res;
125 * Opens a DIR pointer.
127 * @param dirname UTF-8 representation of the directory name
128 * @return a pointer to the DIR struct, or NULL in case of error.
129 * Release with standard closedir().
131 DIR *vlc_opendir (const char *dirname)
133 const char *locname = ToLocaleDup (dirname);
134 if (unlikely(locname == NULL))
136 errno = ENOENT;
137 return NULL;
140 DIR *dir = opendir (locname);
142 free (locname);
144 return dir;
148 * Reads the next file name from an open directory.
150 * @param dir The directory that is being read
152 * @return a UTF-8 string of the directory entry. Use free() to release it.
153 * If there are no more entries in the directory, NULL is returned.
154 * If an error occurs, errno is set and NULL is returned.
156 char *vlc_readdir( DIR *dir )
158 /* Beware that readdir_r() assumes <buf> is large enough to hold the result
159 * dirent including the file name. A buffer overflow could occur otherwise.
160 * In particular, pathconf() and _POSIX_NAME_MAX cannot be used here. */
161 struct dirent *ent;
162 char *path = NULL;
164 /* In the implementation of Innotek LIBC, aka kLIBC on OS/2,
165 * fpathconf (_PC_NAME_MAX) is broken, and errno is set to EBADF.
166 * Moreover, d_name is not the last member of struct dirent.
167 * So just allocate as many as the size of struct dirent. */
168 #if 1
169 long len = sizeof (struct dirent);
170 #else
171 long len = fpathconf (dirfd (dir), _PC_NAME_MAX);
172 len += offsetof (struct dirent, d_name) + 1;
173 #endif
175 struct dirent *buf = malloc (len);
176 if (unlikely(buf == NULL))
177 return NULL;
179 int val = readdir_r (dir, buf, &ent);
180 if (val != 0)
181 errno = val;
182 else if (ent != NULL)
183 path = FromCharset ("", ent->d_name, strlen(ent->d_name));
184 free (buf);
185 return path;
188 static int vlc_statEx (const char *filename, struct stat *buf, bool deref)
190 const char *local_name = ToLocaleDup (filename);
191 if (unlikely(local_name == NULL))
193 errno = ENOENT;
194 return -1;
197 int res = deref ? stat (local_name, buf)
198 : lstat (local_name, buf);
199 free (local_name);
200 return res;
204 * Finds file/inode information, as stat().
205 * Consider using fstat() instead, if possible.
207 * @param filename UTF-8 file path
209 int vlc_stat (const char *filename, struct stat *buf)
211 return vlc_statEx (filename, buf, true);
215 * Finds file/inode information, as lstat().
216 * Consider using fstat() instead, if possible.
218 * @param filename UTF-8 file path
220 int vlc_lstat (const char *filename, struct stat *buf)
222 return vlc_statEx (filename, buf, false);
226 * Removes a file.
228 * @param filename a UTF-8 string with the name of the file you want to delete.
229 * @return A 0 return value indicates success. A -1 return value indicates an
230 * error, and an error code is stored in errno
232 int vlc_unlink (const char *filename)
234 const char *local_name = ToLocaleDup (filename);
235 if (unlikely(local_name == NULL))
237 errno = ENOENT;
238 return -1;
241 int ret = unlink (local_name);
242 free (local_name);
243 return ret;
247 * Moves a file atomically. This only works within a single file system.
249 * @param oldpath path to the file before the move
250 * @param newpath intended path to the file after the move
251 * @return A 0 return value indicates success. A -1 return value indicates an
252 * error, and an error code is stored in errno
254 int vlc_rename (const char *oldpath, const char *newpath)
256 const char *lo = ToLocaleDup (oldpath);
257 if (lo == NULL)
258 goto error;
260 const char *ln = ToLocaleDup (newpath);
261 if (ln == NULL)
263 free (lo);
264 error:
265 errno = ENOENT;
266 return -1;
269 int ret = rename (lo, ln);
270 free (lo);
271 free (ln);
272 return ret;
276 * Determines the current working directory.
278 * @return the current working directory (must be free()'d)
279 * or NULL on error
281 char *vlc_getcwd (void)
283 /* Try $PWD */
284 const char *pwd = getenv ("PWD");
285 if (pwd != NULL)
287 struct stat s1, s2;
288 /* Make sure $PWD is correct */
289 if (stat (pwd, &s1) == 0 && stat (".", &s2) == 0
290 && s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino)
291 return ToLocaleDup (pwd);
294 /* Otherwise iterate getcwd() until the buffer is big enough */
295 long path_max = pathconf (".", _PC_PATH_MAX);
296 size_t size = (path_max == -1 || path_max > 4096) ? 4096 : path_max;
298 for (;; size *= 2)
300 char *buf = malloc (size);
301 if (unlikely(buf == NULL))
302 break;
304 if (getcwd (buf, size) != NULL)
306 char *ret = ToLocaleDup (buf);
307 free (buf);
308 return ret; /* success */
310 free (buf);
312 if (errno != ERANGE)
313 break;
315 return NULL;
319 * Duplicates a file descriptor. The new file descriptor has the close-on-exec
320 * descriptor flag set.
321 * @return a new file descriptor or -1
323 int vlc_dup (int oldfd)
325 int newfd;
327 newfd = dup (oldfd);
328 if (likely(newfd != -1))
329 fcntl (newfd, F_SETFD, FD_CLOEXEC);
331 return newfd;
335 * Creates a pipe (see "man pipe" for further reference).
337 int vlc_pipe (int fds[2])
339 if (pipe (fds))
340 return -1;
342 setmode (fds[0], O_BINARY);
343 setmode (fds[1], O_BINARY);
345 fcntl (fds[0], F_SETFD, FD_CLOEXEC);
346 fcntl (fds[1], F_SETFD, FD_CLOEXEC);
347 return 0;
351 * Writes data to a file descriptor. Unlike write(), if EPIPE error occurs,
352 * this function does not generate a SIGPIPE signal.
353 * @note If the file descriptor is known to be neither a pipe/FIFO nor a
354 * connection-oriented socket, the normal write() should be used.
356 ssize_t vlc_write(int fd, const void *buf, size_t len)
358 struct iovec iov = { .iov_base = (void *)buf, .iov_len = len };
360 return vlc_writev(fd, &iov, 1);
364 * Writes data from an iovec structure to a file descriptor. Unlike writev(),
365 * if EPIPE error occurs, this function does not generate a SIGPIPE signal.
367 ssize_t vlc_writev(int fd, const struct iovec *iov, int count)
369 sigset_t set, oset;
371 sigemptyset(&set);
372 sigaddset(&set, SIGPIPE);
373 pthread_sigmask(SIG_BLOCK, &set, &oset);
375 ssize_t val = writev(fd, iov, count);
376 if (val < 0 && errno == EPIPE)
378 siginfo_t info;
379 struct timespec ts = { 0, 0 };
381 while (sigtimedwait(&set, &info, &ts) >= 0 || errno != EAGAIN);
384 if (!sigismember(&oset, SIGPIPE)) /* Restore the signal mask if changed */
385 pthread_sigmask(SIG_SETMASK, &oset, NULL);
387 return val;
390 #include <vlc_network.h>
393 * Creates a socket file descriptor. The new file descriptor has the
394 * close-on-exec flag set.
395 * @param pf protocol family
396 * @param type socket type
397 * @param proto network protocol
398 * @param nonblock true to create a non-blocking socket
399 * @return a new file descriptor or -1
401 int vlc_socket (int pf, int type, int proto, bool nonblock)
403 int fd;
405 fd = socket (pf, type, proto);
406 if (fd == -1)
407 return -1;
409 fcntl (fd, F_SETFD, FD_CLOEXEC);
410 if (nonblock)
411 fcntl (fd, F_SETFL, fcntl (fd, F_GETFL, 0) | O_NONBLOCK);
412 return fd;
416 * Accepts an inbound connection request on a listening socket.
417 * The new file descriptor has the close-on-exec flag set.
418 * @param lfd listening socket file descriptor
419 * @param addr pointer to the peer address or NULL [OUT]
420 * @param alen pointer to the length of the peer address or NULL [OUT]
421 * @param nonblock whether to put the new socket in non-blocking mode
422 * @return a new file descriptor, or -1 on error.
424 int vlc_accept (int lfd, struct sockaddr *addr, socklen_t *alen, bool nonblock)
428 int fd = accept (lfd, addr, alen);
429 if (fd != -1)
431 fcntl (fd, F_SETFD, FD_CLOEXEC);
432 if (nonblock)
433 fcntl (fd, F_SETFL, fcntl (fd, F_GETFL, 0) | O_NONBLOCK);
434 return fd;
437 while (errno == EINTR);
439 return -1;