]> git.sesse.net Git - vlc/blob - src/os2/filesystem.c
Add TTML fourcc
[vlc] / src / os2 / filesystem.c
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
7  *
8  * Authors: Rémi Denis-Courmont <rem # videolan.org>
9  *          KO Myung-Hun <komh@chollian.net>
10  *
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.
15  *
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.
20  *
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  *****************************************************************************/
25
26 #ifdef HAVE_CONFIG_H
27 # include "config.h"
28 #endif
29
30 #include <assert.h>
31
32 #include <stdio.h>
33 #include <errno.h>
34
35 #include <sys/types.h>
36 #include <unistd.h>
37 #include <fcntl.h>
38 #include <sys/stat.h>
39 #include <dirent.h>
40 #include <sys/socket.h>
41
42 #include <vlc_common.h>
43 #include <vlc_charset.h>
44 #include <vlc_fs.h>
45 #include "libvlc.h" /* vlc_mkdir */
46
47 /**
48  * Opens a system file handle.
49  *
50  * @param filename file path to open (with UTF-8 encoding)
51  * @param flags open() flags, see the C library open() documentation
52  * @return a file handle on success, -1 on error (see errno).
53  * @note Contrary to standard open(), this function returns file handles
54  * with the close-on-exec flag enabled.
55  */
56 int vlc_open (const char *filename, int flags, ...)
57 {
58     unsigned int mode = 0;
59     va_list ap;
60
61     va_start (ap, flags);
62     if (flags & O_CREAT)
63         mode = va_arg (ap, unsigned int);
64     va_end (ap);
65
66     const char *local_name = ToLocale (filename);
67
68     if (local_name == NULL)
69     {
70         errno = ENOENT;
71         return -1;
72     }
73
74     int fd = open (local_name, flags, mode);
75     if (fd != -1)
76         fcntl (fd, F_SETFD, FD_CLOEXEC);
77
78     LocaleFree (local_name);
79     return fd;
80 }
81
82 /**
83  * Opens a system file handle relative to an existing directory handle.
84  *
85  * @param dir directory file descriptor
86  * @param filename file path to open (with UTF-8 encoding)
87  * @param flags open() flags, see the C library open() documentation
88  * @return a file handle on success, -1 on error (see errno).
89  * @note Contrary to standard open(), this function returns file handles
90  * with the close-on-exec flag enabled.
91  */
92 int vlc_openat (int dir, const char *filename, int flags, ...)
93 {
94     errno = ENOSYS;
95
96     return -1;
97 }
98
99
100 /**
101  * Creates a directory using UTF-8 paths.
102  *
103  * @param dirname a UTF-8 string with the name of the directory that you
104  *        want to create.
105  * @param mode directory permissions
106  * @return 0 on success, -1 on error (see errno).
107  */
108 int vlc_mkdir (const char *dirname, mode_t mode)
109 {
110     char *locname = ToLocale (dirname);
111     if (unlikely(locname == NULL))
112     {
113         errno = ENOENT;
114         return -1;
115     }
116
117     int res = mkdir (locname, mode);
118     LocaleFree (locname);
119     return res;
120 }
121
122 /**
123  * Opens a DIR pointer.
124  *
125  * @param dirname UTF-8 representation of the directory name
126  * @return a pointer to the DIR struct, or NULL in case of error.
127  * Release with standard closedir().
128  */
129 DIR *vlc_opendir (const char *dirname)
130 {
131     const char *locname = ToLocale (dirname);
132     if (unlikely(locname == NULL))
133     {
134         errno = ENOENT;
135         return NULL;
136     }
137
138     DIR *dir = opendir (locname);
139
140     LocaleFree (locname);
141
142     return dir;
143 }
144
145 /**
146  * Reads the next file name from an open directory.
147  *
148  * @param dir The directory that is being read
149  *
150  * @return a UTF-8 string of the directory entry. Use free() to release it.
151  * If there are no more entries in the directory, NULL is returned.
152  * If an error occurs, errno is set and NULL is returned.
153  */
154 char *vlc_readdir( DIR *dir )
155 {
156     /* Beware that readdir_r() assumes <buf> is large enough to hold the result
157      * dirent including the file name. A buffer overflow could occur otherwise.
158      * In particular, pathconf() and _POSIX_NAME_MAX cannot be used here. */
159     struct dirent *ent;
160     char *path = NULL;
161
162     /* In the implementation of Innotek LIBC, aka kLIBC on OS/2,
163      * fpathconf (_PC_NAME_MAX) is broken, and errno is set to EBADF.
164      * Moreover, d_name is not the last member of struct dirent.
165      * So just allocate as many as the size of struct dirent. */
166 #if 1
167     long len = sizeof (struct dirent);
168 #else
169     long len = fpathconf (dirfd (dir), _PC_NAME_MAX);
170     len += offsetof (struct dirent, d_name) + 1;
171 #endif
172
173     struct dirent *buf = malloc (len);
174     if (unlikely(buf == NULL))
175         return NULL;
176
177     int val = readdir_r (dir, buf, &ent);
178     if (val != 0)
179         errno = val;
180     else if (ent != NULL)
181         path = FromLocaleDup (ent->d_name);
182     free (buf);
183     return path;
184 }
185
186 static int vlc_statEx (const char *filename, struct stat *buf, bool deref)
187 {
188     const char *local_name = ToLocale (filename);
189     if (unlikely(local_name == NULL))
190     {
191         errno = ENOENT;
192         return -1;
193     }
194
195     int res = deref ? stat (local_name, buf)
196                     : lstat (local_name, buf);
197     LocaleFree (local_name);
198     return res;
199 }
200
201 /**
202  * Finds file/inode information, as stat().
203  * Consider using fstat() instead, if possible.
204  *
205  * @param filename UTF-8 file path
206  */
207 int vlc_stat (const char *filename, struct stat *buf)
208 {
209     return vlc_statEx (filename, buf, true);
210 }
211
212 /**
213  * Finds file/inode information, as lstat().
214  * Consider using fstat() instead, if possible.
215  *
216  * @param filename UTF-8 file path
217  */
218 int vlc_lstat (const char *filename, struct stat *buf)
219 {
220     return vlc_statEx (filename, buf, false);
221 }
222
223 /**
224  * Removes a file.
225  *
226  * @param filename a UTF-8 string with the name of the file you want to delete.
227  * @return A 0 return value indicates success. A -1 return value indicates an
228  *        error, and an error code is stored in errno
229  */
230 int vlc_unlink (const char *filename)
231 {
232     const char *local_name = ToLocale (filename);
233     if (unlikely(local_name == NULL))
234     {
235         errno = ENOENT;
236         return -1;
237     }
238
239     int ret = unlink (local_name);
240     LocaleFree (local_name);
241     return ret;
242 }
243
244 /**
245  * Moves a file atomically. This only works within a single file system.
246  *
247  * @param oldpath path to the file before the move
248  * @param newpath intended path to the file after the move
249  * @return A 0 return value indicates success. A -1 return value indicates an
250  *        error, and an error code is stored in errno
251  */
252 int vlc_rename (const char *oldpath, const char *newpath)
253 {
254     const char *lo = ToLocale (oldpath);
255     if (lo == NULL)
256         goto error;
257
258     const char *ln = ToLocale (newpath);
259     if (ln == NULL)
260     {
261         LocaleFree (lo);
262 error:
263         errno = ENOENT;
264         return -1;
265     }
266
267     int ret = rename (lo, ln);
268     LocaleFree (lo);
269     LocaleFree (ln);
270     return ret;
271 }
272
273 /**
274  * Determines the current working directory.
275  *
276  * @return the current working directory (must be free()'d)
277  *         or NULL on error
278  */
279 char *vlc_getcwd (void)
280 {
281     /* Try $PWD */
282     const char *pwd = getenv ("PWD");
283     if (pwd != NULL)
284     {
285         struct stat s1, s2;
286         /* Make sure $PWD is correct */
287         if (stat (pwd, &s1) == 0 && stat (".", &s2) == 0
288          && s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino)
289             return ToLocaleDup (pwd);
290     }
291
292     /* Otherwise iterate getcwd() until the buffer is big enough */
293     long path_max = pathconf (".", _PC_PATH_MAX);
294     size_t size = (path_max == -1 || path_max > 4096) ? 4096 : path_max;
295
296     for (;; size *= 2)
297     {
298         char *buf = malloc (size);
299         if (unlikely(buf == NULL))
300             break;
301
302         if (getcwd (buf, size) != NULL)
303         {
304             char *ret = ToLocaleDup (buf);
305             free (buf);
306             return ret; /* success */
307         }
308         free (buf);
309
310         if (errno != ERANGE)
311             break;
312     }
313     return NULL;
314 }
315
316 /**
317  * Duplicates a file descriptor. The new file descriptor has the close-on-exec
318  * descriptor flag set.
319  * @return a new file descriptor or -1
320  */
321 int vlc_dup (int oldfd)
322 {
323     int newfd;
324
325     newfd = dup (oldfd);
326     if (likely(newfd != -1))
327         fcntl (newfd, F_SETFD, FD_CLOEXEC);
328
329     return newfd;
330 }
331
332 /**
333  * Creates a pipe (see "man pipe" for further reference).
334  */
335 int vlc_pipe (int fds[2])
336 {
337     if (pipe (fds))
338         return -1;
339
340     fcntl (fds[0], F_SETFD, FD_CLOEXEC);
341     fcntl (fds[1], F_SETFD, FD_CLOEXEC);
342     return 0;
343 }
344
345 #include <vlc_network.h>
346
347 /**
348  * Creates a socket file descriptor. The new file descriptor has the
349  * close-on-exec flag set.
350  * @param pf protocol family
351  * @param type socket type
352  * @param proto network protocol
353  * @param nonblock true to create a non-blocking socket
354  * @return a new file descriptor or -1
355  */
356 int vlc_socket (int pf, int type, int proto, bool nonblock)
357 {
358     int fd;
359
360     fd = socket (pf, type, proto);
361     if (fd == -1)
362         return -1;
363
364     fcntl (fd, F_SETFD, FD_CLOEXEC);
365     if (nonblock)
366         fcntl (fd, F_SETFL, fcntl (fd, F_GETFL, 0) | O_NONBLOCK);
367     return fd;
368 }
369
370 /**
371  * Accepts an inbound connection request on a listening socket.
372  * The new file descriptor has the close-on-exec flag set.
373  * @param lfd listening socket file descriptor
374  * @param addr pointer to the peer address or NULL [OUT]
375  * @param alen pointer to the length of the peer address or NULL [OUT]
376  * @param nonblock whether to put the new socket in non-blocking mode
377  * @return a new file descriptor, or -1 on error.
378  */
379 int vlc_accept (int lfd, struct sockaddr *addr, socklen_t *alen, bool nonblock)
380 {
381     do
382     {
383         int fd = accept (lfd, addr, alen);
384         if (fd != -1)
385         {
386             fcntl (fd, F_SETFD, FD_CLOEXEC);
387             if (nonblock)
388                 fcntl (fd, F_SETFL, fcntl (fd, F_GETFL, 0) | O_NONBLOCK);
389             return fd;
390         }
391     }
392     while (errno == EINTR);
393
394     return -1;
395 }