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 <vlc_network.h>
48 #include "libvlc.h" /* vlc_mkdir */
50 int vlc_open (const char *filename
, int flags
, ...)
52 unsigned int mode
= 0;
57 mode
= va_arg (ap
, unsigned int);
60 const char *local_name
= ToLocaleDup (filename
);
62 if (local_name
== NULL
)
68 int fd
= open (local_name
, flags
, mode
);
70 fcntl (fd
, F_SETFD
, FD_CLOEXEC
);
76 int vlc_openat (int dir
, const char *filename
, int flags
, ...)
89 int vlc_close (int fd
)
94 int vlc_mkdir (const char *dirname
, mode_t mode
)
96 char *locname
= ToLocaleDup (dirname
);
97 if (unlikely(locname
== NULL
))
103 int res
= mkdir (locname
, mode
);
108 DIR *vlc_opendir (const char *dirname
)
110 const char *locname
= ToLocaleDup (dirname
);
111 if (unlikely(locname
== NULL
))
117 DIR *dir
= opendir (locname
);
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. */
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. */
137 long len
= sizeof (struct dirent
);
139 long len
= fpathconf (dirfd (dir
), _PC_NAME_MAX
);
140 len
+= offsetof (struct dirent
, d_name
) + 1;
143 struct dirent
*buf
= malloc (len
);
144 if (unlikely(buf
== NULL
))
147 int val
= readdir_r (dir
, buf
, &ent
);
150 else if (ent
!= NULL
)
151 path
= FromCharset ("", ent
->d_name
, strlen(ent
->d_name
));
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
))
165 int res
= deref
? stat (local_name
, buf
)
166 : lstat (local_name
, buf
);
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
))
190 int ret
= unlink (local_name
);
195 int vlc_rename (const char *oldpath
, const char *newpath
)
197 const char *lo
= ToLocaleDup (oldpath
);
201 const char *ln
= ToLocaleDup (newpath
);
210 int ret
= rename (lo
, ln
);
216 char *vlc_getcwd (void)
219 const char *pwd
= getenv ("PWD");
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
;
235 char *buf
= malloc (size
);
236 if (unlikely(buf
== NULL
))
239 if (getcwd (buf
, size
) != NULL
)
241 char *ret
= ToLocaleDup (buf
);
243 return ret
; /* success */
253 int vlc_dup (int oldfd
)
258 if (likely(newfd
!= -1))
259 fcntl (newfd
, F_SETFD
, FD_CLOEXEC
);
264 int vlc_pipe (int fds
[2])
266 if (vlc_socketpair (AF_LOCAL
, SOCK_STREAM
, 0, fds
, false))
269 shutdown (fds
[0], SHUT_WR
);
270 shutdown (fds
[1], SHUT_RD
);
272 setmode (fds
[0], O_BINARY
);
273 setmode (fds
[1], O_BINARY
);
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
)
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
)
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
);
308 static void vlc_socket_setup(int fd
, bool nonblock
)
310 fcntl(fd
, F_SETFD
, FD_CLOEXEC
);
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
);
320 vlc_socket_setup(fd
, nonblock
);
324 int vlc_socketpair(int pf
, int type
, int proto
, int fds
[2], bool nonblock
)
326 if (socketpair(pf
, type
, proto
, fds
))
329 vlc_socket_setup(fds
[0], nonblock
);
330 vlc_socket_setup(fds
[1], nonblock
);
334 int vlc_accept (int lfd
, struct sockaddr
*addr
, socklen_t
*alen
, bool nonblock
)
338 int fd
= accept (lfd
, addr
, alen
);
341 fcntl (fd
, F_SETFD
, FD_CLOEXEC
);
343 fcntl (fd
, F_SETFL
, fcntl (fd
, F_GETFL
, 0) | O_NONBLOCK
);
347 while (errno
== EINTR
);