1/* 2 * various OS-feature replacement utilities 3 * copyright (c) 2000, 2001, 2002 Fabrice Bellard 4 * 5 * This file is part of FFmpeg. 6 * 7 * FFmpeg is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU Lesser General Public 9 * License as published by the Free Software Foundation; either 10 * version 2.1 of the License, or (at your option) any later version. 11 * 12 * FFmpeg is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 15 * Lesser General Public License for more details. 16 * 17 * You should have received a copy of the GNU Lesser General Public 18 * License along with FFmpeg; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 20 */ 21 22#ifndef AVFORMAT_OS_SUPPORT_H 23#define AVFORMAT_OS_SUPPORT_H 24 25/** 26 * @file 27 * miscellaneous OS support macros and functions. 28 */ 29 30#include "config.h" 31 32#include <sys/stat.h> 33 34#ifdef _WIN32 35#if HAVE_DIRECT_H 36#include <direct.h> 37#endif 38#if HAVE_IO_H 39#include <io.h> 40#endif 41#endif 42 43#ifdef _WIN32 44# include <fcntl.h> 45# ifdef lseek 46# undef lseek 47# endif 48# define lseek(f,p,w) _lseeki64((f), (p), (w)) 49# ifdef stat 50# undef stat 51# endif 52 53# define stat win32_stat 54 55 /* 56 * The POSIX definition for the stat() function uses a struct of the 57 * same name (struct stat), that why it takes this extra effort for 58 * redirecting/replacing the stat() function with our own one which 59 * is capable to handle long path names on Windows. 60 * The struct below roughly follows the POSIX definition. Time values 61 * are 64bit, but in cases when _USE_32BIT_TIME_T is defined, they 62 * will be set to values no larger than INT32_MAX which corresponds 63 * to file times up to the year 2038. 64 */ 65 struct win32_stat 66 { 67 _dev_t st_dev; /* ID of device containing file */ 68 _ino_t st_ino; /* inode number */ 69 unsigned short st_mode; /* protection */ 70 short st_nlink; /* number of hard links */ 71 short st_uid; /* user ID of owner */ 72 short st_gid; /* group ID of owner */ 73 _dev_t st_rdev; /* device ID (if special file) */ 74 int64_t st_size; /* total size, in bytes */ 75 int64_t st_atime; /* time of last access */ 76 int64_t st_mtime; /* time of last modification */ 77 int64_t st_ctime; /* time of last status change */ 78 }; 79 80# ifdef fstat 81# undef fstat 82# endif 83# define fstat win32_fstat 84#endif /* defined(_WIN32) */ 85 86 87#ifdef __ANDROID__ 88# if HAVE_UNISTD_H 89# include <unistd.h> 90# endif 91# ifdef lseek 92# undef lseek 93# endif 94# define lseek(f,p,w) lseek64((f), (p), (w)) 95#endif 96 97static inline int is_dos_path(const char *path) 98{ 99#if HAVE_DOS_PATHS 100 if (path[0] && path[1] == ':') 101 return 1; 102#endif 103 return 0; 104} 105 106#if defined(_WIN32) 107#ifndef S_IRUSR 108#define S_IRUSR S_IREAD 109#endif 110#ifndef S_IWUSR 111#define S_IWUSR S_IWRITE 112#endif 113#endif 114 115#if CONFIG_NETWORK 116#if defined(_WIN32) 117#define SHUT_RD SD_RECEIVE 118#define SHUT_WR SD_SEND 119#define SHUT_RDWR SD_BOTH 120#else 121#include <sys/socket.h> 122#if !defined(SHUT_RD) /* OS/2, DJGPP */ 123#define SHUT_RD 0 124#define SHUT_WR 1 125#define SHUT_RDWR 2 126#endif 127#endif 128 129#if !HAVE_SOCKLEN_T 130typedef int socklen_t; 131#endif 132 133/* most of the time closing a socket is just closing an fd */ 134#if !HAVE_CLOSESOCKET 135#define closesocket close 136#endif 137 138#if !HAVE_POLL_H 139typedef unsigned long nfds_t; 140 141#if HAVE_WINSOCK2_H 142#include <winsock2.h> 143#endif 144#if !HAVE_STRUCT_POLLFD 145struct pollfd { 146 int fd; 147 short events; /* events to look for */ 148 short revents; /* events that occurred */ 149}; 150 151/* events & revents */ 152#define POLLIN 0x0001 /* any readable data available */ 153#define POLLOUT 0x0002 /* file descriptor is writeable */ 154#define POLLRDNORM POLLIN 155#define POLLWRNORM POLLOUT 156#define POLLRDBAND 0x0008 /* priority readable data */ 157#define POLLWRBAND 0x0010 /* priority data can be written */ 158#define POLLPRI 0x0020 /* high priority readable data */ 159 160/* revents only */ 161#define POLLERR 0x0004 /* errors pending */ 162#define POLLHUP 0x0080 /* disconnected */ 163#define POLLNVAL 0x1000 /* invalid file descriptor */ 164#endif 165 166 167int ff_poll(struct pollfd *fds, nfds_t numfds, int timeout); 168#define poll ff_poll 169#endif /* HAVE_POLL_H */ 170#endif /* CONFIG_NETWORK */ 171 172#ifdef _WIN32 173#include <stdio.h> 174#include <windows.h> 175#include "libavutil/wchar_filename.h" 176 177#define DEF_FS_FUNCTION(name, wfunc, afunc) \ 178static inline int win32_##name(const char *filename_utf8) \ 179{ \ 180 wchar_t *filename_w; \ 181 int ret; \ 182 \ 183 if (get_extended_win32_path(filename_utf8, &filename_w)) \ 184 return -1; \ 185 if (!filename_w) \ 186 goto fallback; \ 187 \ 188 ret = wfunc(filename_w); \ 189 av_free(filename_w); \ 190 return ret; \ 191 \ 192fallback: \ 193 /* filename may be be in CP_ACP */ \ 194 return afunc(filename_utf8); \ 195} 196 197DEF_FS_FUNCTION(unlink, _wunlink, _unlink) 198DEF_FS_FUNCTION(mkdir, _wmkdir, _mkdir) 199DEF_FS_FUNCTION(rmdir, _wrmdir , _rmdir) 200 201static inline int win32_access(const char *filename_utf8, int mode) 202{ 203 wchar_t *filename_w; 204 int ret; 205 if (get_extended_win32_path(filename_utf8, &filename_w)) 206 return -1; 207 if (!filename_w) 208 goto fallback; 209 ret = _waccess(filename_w, mode); 210 av_free(filename_w); 211 return ret; 212fallback: 213 return _access(filename_utf8, mode); 214} 215 216static inline void copy_stat(struct _stat64 *crtstat, struct win32_stat *buf) 217{ 218 buf->st_dev = crtstat->st_dev; 219 buf->st_ino = crtstat->st_ino; 220 buf->st_mode = crtstat->st_mode; 221 buf->st_nlink = crtstat->st_nlink; 222 buf->st_uid = crtstat->st_uid; 223 buf->st_gid = crtstat->st_gid; 224 buf->st_rdev = crtstat->st_rdev; 225 buf->st_size = crtstat->st_size; 226 buf->st_atime = crtstat->st_atime; 227 buf->st_mtime = crtstat->st_mtime; 228 buf->st_ctime = crtstat->st_ctime; 229} 230 231static inline int win32_stat(const char *filename_utf8, struct win32_stat *buf) 232{ 233 struct _stat64 crtstat = { 0 }; 234 wchar_t *filename_w; 235 int ret; 236 237 if (get_extended_win32_path(filename_utf8, &filename_w)) 238 return -1; 239 240 if (filename_w) { 241 ret = _wstat64(filename_w, &crtstat); 242 av_free(filename_w); 243 } else 244 ret = _stat64(filename_utf8, &crtstat); 245 246 copy_stat(&crtstat, buf); 247 248 return ret; 249} 250 251static inline int win32_fstat(int fd, struct win32_stat *buf) 252{ 253 struct _stat64 crtstat = { 0 }; 254 int ret; 255 256 ret = _fstat64(fd, &crtstat); 257 258 copy_stat(&crtstat, buf); 259 260 return ret; 261} 262 263static inline int win32_rename(const char *src_utf8, const char *dest_utf8) 264{ 265 wchar_t *src_w, *dest_w; 266 int ret; 267 268 if (get_extended_win32_path(src_utf8, &src_w)) 269 return -1; 270 if (get_extended_win32_path(dest_utf8, &dest_w)) { 271 av_free(src_w); 272 return -1; 273 } 274 if (!src_w || !dest_w) { 275 av_free(src_w); 276 av_free(dest_w); 277 goto fallback; 278 } 279 280 ret = MoveFileExW(src_w, dest_w, MOVEFILE_REPLACE_EXISTING); 281 av_free(src_w); 282 av_free(dest_w); 283 // Lacking proper mapping from GetLastError() error codes to errno codes 284 if (ret) 285 errno = EPERM; 286 return ret; 287 288fallback: 289 /* filename may be be in CP_ACP */ 290#if !HAVE_UWP 291 ret = MoveFileExA(src_utf8, dest_utf8, MOVEFILE_REPLACE_EXISTING); 292 if (ret) 293 errno = EPERM; 294#else 295 /* Windows Phone doesn't have MoveFileExA, and for Windows Store apps, 296 * it is available but not allowed by the app certification kit. However, 297 * it's unlikely that anybody would input filenames in CP_ACP there, so this 298 * fallback is kept mostly for completeness. Alternatively we could 299 * do MultiByteToWideChar(CP_ACP) and use MoveFileExW, but doing 300 * explicit conversions with CP_ACP is allegedly forbidden in windows 301 * store apps (or windows phone), and the notion of a native code page 302 * doesn't make much sense there. */ 303 ret = rename(src_utf8, dest_utf8); 304#endif 305 return ret; 306} 307 308#define mkdir(a, b) win32_mkdir(a) 309#define rename win32_rename 310#define rmdir win32_rmdir 311#define unlink win32_unlink 312#define access win32_access 313 314#endif 315 316#endif /* AVFORMAT_OS_SUPPORT_H */ 317