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 *****************************************************************************/
35 #include <sys/types.h>
41 #include <sys/socket.h>
44 #include <vlc_common.h>
45 #include <vlc_charset.h>
47 #include "libvlc.h" /* vlc_mkdir */
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;
65 mode
= va_arg (ap
, unsigned int);
68 const char *local_name
= ToLocaleDup (filename
);
70 if (local_name
== NULL
)
76 int fd
= open (local_name
, flags
, mode
);
78 fcntl (fd
, F_SETFD
, FD_CLOEXEC
);
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
, ...)
103 * Creates a directory using UTF-8 paths.
105 * @param dirname a UTF-8 string with the name of the directory that you
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
))
119 int res
= mkdir (locname
, mode
);
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
))
140 DIR *dir
= opendir (locname
);
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. */
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. */
169 long len
= sizeof (struct dirent
);
171 long len
= fpathconf (dirfd (dir
), _PC_NAME_MAX
);
172 len
+= offsetof (struct dirent
, d_name
) + 1;
175 struct dirent
*buf
= malloc (len
);
176 if (unlikely(buf
== NULL
))
179 int val
= readdir_r (dir
, buf
, &ent
);
182 else if (ent
!= NULL
)
183 path
= FromCharset ("", ent
->d_name
, strlen(ent
->d_name
));
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
))
197 int res
= deref
? stat (local_name
, buf
)
198 : lstat (local_name
, buf
);
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);
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
))
241 int ret
= unlink (local_name
);
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
);
260 const char *ln
= ToLocaleDup (newpath
);
269 int ret
= rename (lo
, ln
);
276 * Determines the current working directory.
278 * @return the current working directory (must be free()'d)
281 char *vlc_getcwd (void)
284 const char *pwd
= getenv ("PWD");
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
;
300 char *buf
= malloc (size
);
301 if (unlikely(buf
== NULL
))
304 if (getcwd (buf
, size
) != NULL
)
306 char *ret
= ToLocaleDup (buf
);
308 return ret
; /* success */
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
)
328 if (likely(newfd
!= -1))
329 fcntl (newfd
, F_SETFD
, FD_CLOEXEC
);
335 * Creates a pipe (see "man pipe" for further reference).
337 int vlc_pipe (int fds
[2])
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
);
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
)
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
)
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
);
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
)
405 fd
= socket (pf
, type
, proto
);
409 fcntl (fd
, F_SETFD
, FD_CLOEXEC
);
411 fcntl (fd
, F_SETFL
, fcntl (fd
, F_GETFL
, 0) | O_NONBLOCK
);
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
);
431 fcntl (fd
, F_SETFD
, FD_CLOEXEC
);
433 fcntl (fd
, F_SETFL
, fcntl (fd
, F_GETFL
, 0) | O_NONBLOCK
);
437 while (errno
== EINTR
);