qt: playlist: use item title if available
[vlc.git] / src / posix / filesystem.c
blob18105a643cb71baada2cffce56dd8da8c477d3e9
1 /*****************************************************************************
2 * filesystem.c: POSIX file system helpers
3 *****************************************************************************
4 * Copyright (C) 2005-2006 VLC authors and VideoLAN
5 * Copyright © 2005-2008 Rémi Denis-Courmont
7 * Authors: Rémi Denis-Courmont
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 #ifdef HAVE_CONFIG_H
25 # include "config.h"
26 #endif
28 #include <assert.h>
30 #include <stdio.h>
31 #include <limits.h> /* NAME_MAX */
32 #include <errno.h>
33 #include <signal.h>
35 #include <sys/types.h>
36 #include <sys/uio.h>
37 #include <unistd.h>
38 #include <fcntl.h>
39 #include <sys/stat.h>
40 #include <dirent.h>
41 #ifdef HAVE_SYS_SOCKET_H
42 #include <sys/socket.h>
43 #endif
45 #include <vlc_common.h>
46 #include <vlc_fs.h>
48 #if !defined(HAVE_ACCEPT4)
49 static inline void vlc_cloexec(int fd)
51 fcntl(fd, F_SETFD, FD_CLOEXEC | fcntl(fd, F_GETFD));
53 #endif
54 #if !defined(MSG_NOSIGNAL) && defined(SO_NOSIGPIPE)
55 # define MSG_NOSIGNAL 0
56 #endif
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 return open(filename, flags | O_CLOEXEC, mode);
71 int vlc_openat (int dir, const char *filename, int flags, ...)
73 unsigned int mode = 0;
74 va_list ap;
76 va_start (ap, flags);
77 if (flags & O_CREAT)
78 mode = va_arg (ap, unsigned int);
79 va_end (ap);
81 return openat(dir, filename, flags | O_CLOEXEC, mode);
84 #ifdef HAVE_MKOSTEMP
85 int vlc_mkstemp (char *template)
87 return mkostemp(template, O_CLOEXEC);
89 #endif
91 VLC_WEAK int vlc_memfd(void)
93 char bufpath[] = "/tmp/"PACKAGE_NAME"XXXXXX";
94 int fd;
96 fd = vlc_mkstemp (bufpath);
97 if (fd != -1)
98 unlink (bufpath);
99 return fd;
102 int vlc_close (int fd)
104 int ret;
105 #ifdef POSIX_CLOSE_RESTART
106 ret = posix_close(fd, 0);
107 #else
108 ret = close(fd);
109 /* POSIX.2008 (and earlier) does not specify if the file descriptor is
110 * closed on failure. Assume it is as on Linux and most other common OSes.
111 * Also emulate the correct error code as per newer POSIX versions. */
112 if (unlikely(ret != 0) && unlikely(errno == EINTR))
113 errno = EINPROGRESS;
114 #endif
115 assert(ret == 0 || errno != EBADF); /* something is corrupt? */
116 return ret;
119 int vlc_mkdir (const char *dirname, mode_t mode)
121 return mkdir (dirname, mode);
124 DIR *vlc_opendir (const char *dirname)
126 return opendir (dirname);
129 const char *vlc_readdir(DIR *dir)
131 struct dirent *ent = readdir (dir);
132 return (ent != NULL) ? ent->d_name : NULL;
135 int vlc_stat (const char *filename, struct stat *buf)
137 return stat (filename, buf);
140 int vlc_lstat (const char *filename, struct stat *buf)
142 return lstat (filename, buf);
145 int vlc_unlink (const char *filename)
147 return unlink (filename);
150 int vlc_rename (const char *oldpath, const char *newpath)
152 return rename (oldpath, newpath);
155 char *vlc_getcwd (void)
157 long path_max = pathconf (".", _PC_PATH_MAX);
158 size_t size = (path_max == -1 || path_max > 4096) ? 4096 : path_max;
160 for (;; size *= 2)
162 char *buf = malloc (size);
163 if (unlikely(buf == NULL))
164 break;
166 if (getcwd (buf, size) != NULL)
167 return buf;
168 free (buf);
170 if (errno != ERANGE)
171 break;
173 return NULL;
176 int vlc_dup (int oldfd)
178 return fcntl (oldfd, F_DUPFD_CLOEXEC, 0);
181 int vlc_dup2(int oldfd, int newfd)
183 #ifdef HAVE_DUP3
184 return dup3(oldfd, newfd, O_CLOEXEC);
185 #else
186 int ret = dup2(oldfd, newfd);
187 if (ret >= 0)
188 vlc_cloexec(newfd);
189 return ret;
190 #endif
193 int vlc_pipe (int fds[2])
195 #ifdef HAVE_PIPE2
196 return pipe2(fds, O_CLOEXEC);
197 #else
198 int ret = pipe(fds);
199 if (ret == 0)
201 vlc_cloexec(fds[0]);
202 vlc_cloexec(fds[1]);
204 return ret;
205 #endif
208 ssize_t vlc_write(int fd, const void *buf, size_t len)
210 struct iovec iov = { .iov_base = (void *)buf, .iov_len = len };
212 return vlc_writev(fd, &iov, 1);
215 ssize_t vlc_writev(int fd, const struct iovec *iov, int count)
217 sigset_t set, oset;
219 sigemptyset(&set);
220 sigaddset(&set, SIGPIPE);
221 pthread_sigmask(SIG_BLOCK, &set, &oset);
223 ssize_t val = writev(fd, iov, count);
224 if (val < 0 && errno == EPIPE)
226 #if (_POSIX_REALTIME_SIGNALS > 0)
227 siginfo_t info;
228 struct timespec ts = { 0, 0 };
230 while (sigtimedwait(&set, &info, &ts) >= 0 || errno != EAGAIN);
231 #else
232 for (;;)
234 sigset_t s;
235 int num;
237 sigpending(&s);
238 if (!sigismember(&s, SIGPIPE))
239 break;
241 sigwait(&set, &num);
242 assert(num == SIGPIPE);
244 #endif
247 if (!sigismember(&oset, SIGPIPE)) /* Restore the signal mask if changed */
248 pthread_sigmask(SIG_SETMASK, &oset, NULL);
249 return val;
252 #include <vlc_network.h>
254 #ifndef HAVE_ACCEPT4
255 static void vlc_socket_setup(int fd, bool nonblock)
257 vlc_cloexec(fd);
259 if (nonblock)
260 fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
262 #ifdef SO_NOSIGPIPE
263 setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){ 1 }, sizeof (int));
264 #endif
266 #endif
268 int vlc_socket (int pf, int type, int proto, bool nonblock)
270 #ifdef SOCK_CLOEXEC
271 if (nonblock)
272 type |= SOCK_NONBLOCK;
274 int fd = socket(pf, type | SOCK_CLOEXEC, proto);
275 # ifdef SO_NOSIGPIPE
276 if (fd != -1)
277 setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){ 1 }, sizeof (int));
278 # endif
279 #else
280 int fd = socket (pf, type, proto);
281 if (fd != -1)
282 vlc_socket_setup(fd, nonblock);
283 #endif
284 return fd;
287 int vlc_socketpair(int pf, int type, int proto, int fds[2], bool nonblock)
289 #ifdef SOCK_CLOEXEC
290 if (nonblock)
291 type |= SOCK_NONBLOCK;
293 int ret = socketpair(pf, type | SOCK_CLOEXEC, proto, fds);
294 # ifdef SO_NOSIGPIPE
295 if (ret == 0)
297 const int val = 1;
299 setsockopt(fds[0], SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof (val));
300 setsockopt(fds[1], SOL_SOCKET, SO_NOSIGPIPE, &val, sizeof (val));
302 # endif
303 #else
304 int ret = socketpair(pf, type, proto, fds);
305 if (ret == 0)
307 vlc_socket_setup(fds[0], nonblock);
308 vlc_socket_setup(fds[1], nonblock);
310 #endif
311 return ret;
314 int vlc_accept (int lfd, struct sockaddr *addr, socklen_t *alen, bool nonblock)
316 #ifdef HAVE_ACCEPT4
317 int flags = SOCK_CLOEXEC;
318 if (nonblock)
319 flags |= SOCK_NONBLOCK;
321 int fd = accept4(lfd, addr, alen, flags);
322 # ifdef SO_NOSIGPIPE
323 if (fd != -1)
324 setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, &(int){ 1 }, sizeof (int));
325 # endif
326 #else
327 int fd = accept(lfd, addr, alen);
328 if (fd != -1)
329 vlc_socket_setup(fd, nonblock);
330 #endif
331 return fd;
334 ssize_t vlc_send(int fd, const void *buf, size_t len, int flags)
336 return vlc_sendto(fd, buf, len, flags, NULL, 0);
339 ssize_t vlc_sendto(int fd, const void *buf, size_t len, int flags,
340 const struct sockaddr *dst, socklen_t dstlen)
342 struct iovec iov = {
343 .iov_base = (void *)buf,
344 .iov_len = len,
346 struct msghdr msg = {
347 .msg_name = (struct sockaddr *)dst,
348 .msg_namelen = dstlen,
349 .msg_iov = &iov,
350 .msg_iovlen = 1,
353 return vlc_sendmsg(fd, &msg, flags);
356 ssize_t vlc_sendmsg(int fd, const struct msghdr *msg, int flags)
358 return sendmsg(fd, msg, flags | MSG_NOSIGNAL);