1 /*****************************************************************************
2 * file.c: file input (file: access plug-in)
3 *****************************************************************************
4 * Copyright (C) 2001-2006 VLC authors and VideoLAN
5 * Copyright © 2006-2007 Rémi Denis-Courmont
8 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9 * Rémi Denis-Courmont <rem # videolan # org>
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 *****************************************************************************/
32 #include <sys/types.h>
36 # include <sys/statvfs.h>
37 # if defined (HAVE_SYS_MOUNT_H)
38 # include <sys/param.h>
39 # include <sys/mount.h>
42 #ifdef HAVE_LINUX_MAGIC_H
44 # include <linux/magic.h>
56 #include <vlc_common.h>
58 #include <vlc_input.h>
59 #include <vlc_access.h>
61 # include <vlc_charset.h>
65 #include <vlc_interrupt.h>
74 #if !defined (_WIN32) && !defined (__OS2__)
75 static bool IsRemote (int fd
)
77 #if defined (HAVE_FSTATVFS) && defined (MNT_LOCAL)
80 if (fstatvfs (fd
, &stf
))
82 /* fstatvfs() is in POSIX, but MNT_LOCAL is not */
83 return !(stf
.f_flag
& MNT_LOCAL
);
85 #elif defined (HAVE_LINUX_MAGIC_H)
88 if (fstatfs (fd
, &stf
))
91 switch ((unsigned long)stf
.f_type
)
94 case CODA_SUPER_MAGIC
:
98 case 0xFF534D42 /*CIFS_MAGIC_NUMBER*/:
109 # define IsRemote(fd,path) IsRemote(fd)
111 #else /* _WIN32 || __OS2__ */
112 static bool IsRemote (const char *path
)
114 # if !defined(__OS2__) && !VLC_WINSTORE_APP
115 wchar_t *wpath
= ToWide (path
);
116 bool is_remote
= (wpath
!= NULL
&& PathIsNetworkPathW (wpath
));
120 return (! strncmp(path
, "\\\\", 2));
123 # define IsRemote(fd,path) IsRemote(path)
126 #ifndef HAVE_POSIX_FADVISE
127 # define posix_fadvise(fd, off, len, adv)
130 static ssize_t
Read (stream_t
*, void *, size_t);
131 static int FileSeek (stream_t
*, uint64_t);
132 static int NoSeek (stream_t
*, uint64_t);
133 static int FileControl (stream_t
*, int, va_list);
135 /*****************************************************************************
136 * FileOpen: open the file
137 *****************************************************************************/
138 int FileOpen( vlc_object_t
*p_this
)
140 stream_t
*p_access
= (stream_t
*)p_this
;
145 if (!strcasecmp (p_access
->psz_name
, "fd"))
148 int oldfd
= strtol (p_access
->psz_location
, &end
, 10);
151 fd
= vlc_dup (oldfd
);
152 else if (*end
== '/' && end
> p_access
->psz_location
)
154 char *name
= vlc_uri_decode_duplicate (end
- 1);
158 fd
= vlc_openat (oldfd
, name
, O_RDONLY
| O_NONBLOCK
);
165 if (unlikely(p_access
->psz_filepath
== NULL
))
167 fd
= vlc_open (p_access
->psz_filepath
, O_RDONLY
| O_NONBLOCK
);
172 msg_Err (p_access
, "cannot open file %s (%s)",
173 p_access
->psz_filepath
? p_access
->psz_filepath
174 : p_access
->psz_location
,
175 vlc_strerror_c(errno
));
182 msg_Err (p_access
, "read error: %s", vlc_strerror_c(errno
));
187 /* Force blocking mode back */
188 fcntl (fd
, F_SETFL
, fcntl (fd
, F_GETFL
) & ~O_NONBLOCK
);
191 /* Directories can be opened and read from, but only readdir() knows
192 * how to parse the data. The directory plugin will do it. */
193 if (S_ISDIR (st
.st_mode
))
195 #ifdef HAVE_FDOPENDIR
196 DIR *p_dir
= fdopendir(fd
);
198 msg_Err (p_access
, "fdopendir error: %s", vlc_strerror_c(errno
));
201 return DirInit (p_access
, p_dir
);
203 msg_Dbg (p_access
, "ignoring directory");
208 access_sys_t
*p_sys
= vlc_obj_malloc(p_this
, sizeof (*p_sys
));
209 if (unlikely(p_sys
== NULL
))
211 p_access
->pf_read
= Read
;
212 p_access
->pf_block
= NULL
;
213 p_access
->pf_control
= FileControl
;
214 p_access
->p_sys
= p_sys
;
217 if (S_ISREG (st
.st_mode
) || S_ISBLK (st
.st_mode
))
219 p_access
->pf_seek
= FileSeek
;
220 p_sys
->b_pace_control
= true;
222 /* Demuxers will need the beginning of the file for probing. */
223 posix_fadvise (fd
, 0, 4096, POSIX_FADV_WILLNEED
);
224 /* In most cases, we only read the file once. */
225 posix_fadvise (fd
, 0, 0, POSIX_FADV_NOREUSE
);
227 fcntl (fd
, F_NOCACHE
, 0);
230 if (IsRemote(fd
, p_access
->psz_filepath
))
231 fcntl (fd
, F_RDAHEAD
, 0);
233 fcntl (fd
, F_RDAHEAD
, 1);
238 p_access
->pf_seek
= NoSeek
;
239 p_sys
->b_pace_control
= strcasecmp (p_access
->psz_name
, "stream");
249 /*****************************************************************************
250 * FileClose: close the target
251 *****************************************************************************/
252 void FileClose (vlc_object_t
* p_this
)
254 stream_t
*p_access
= (stream_t
*)p_this
;
256 if (p_access
->pf_read
== NULL
)
262 access_sys_t
*p_sys
= p_access
->p_sys
;
264 vlc_close (p_sys
->fd
);
268 static ssize_t
Read (stream_t
*p_access
, void *p_buffer
, size_t i_len
)
270 access_sys_t
*p_sys
= p_access
->p_sys
;
273 ssize_t val
= vlc_read_i11e (fd
, p_buffer
, i_len
);
283 msg_Err (p_access
, "read error: %s", vlc_strerror_c(errno
));
290 /*****************************************************************************
291 * Seek: seek to a specific location in a file
292 *****************************************************************************/
293 static int FileSeek (stream_t
*p_access
, uint64_t i_pos
)
295 access_sys_t
*sys
= p_access
->p_sys
;
297 if (lseek(sys
->fd
, i_pos
, SEEK_SET
) == (off_t
)-1)
302 static int NoSeek (stream_t
*p_access
, uint64_t i_pos
)
304 /* vlc_assert_unreachable(); ?? */
305 (void) p_access
; (void) i_pos
;
309 /*****************************************************************************
311 *****************************************************************************/
312 static int FileControl( stream_t
*p_access
, int i_query
, va_list args
)
314 access_sys_t
*p_sys
= p_access
->p_sys
;
320 case STREAM_CAN_SEEK
:
321 case STREAM_CAN_FASTSEEK
:
322 pb_bool
= va_arg( args
, bool * );
323 *pb_bool
= (p_access
->pf_seek
!= NoSeek
);
326 case STREAM_CAN_PAUSE
:
327 case STREAM_CAN_CONTROL_PACE
:
328 pb_bool
= va_arg( args
, bool * );
329 *pb_bool
= p_sys
->b_pace_control
;
332 case STREAM_GET_SIZE
:
336 if (fstat (p_sys
->fd
, &st
) || !S_ISREG(st
.st_mode
))
338 *va_arg( args
, uint64_t * ) = st
.st_size
;
342 case STREAM_GET_PTS_DELAY
:
343 pi_64
= va_arg( args
, vlc_tick_t
* );
344 if (IsRemote (p_sys
->fd
, p_access
->psz_filepath
))
345 *pi_64
= VLC_TICK_FROM_MS(
346 var_InheritInteger (p_access
, "network-caching") );
348 *pi_64
= VLC_TICK_FROM_MS(
349 var_InheritInteger (p_access
, "file-caching") );
352 case STREAM_SET_PAUSE_STATE
: