~ubuntu-branches/ubuntu/natty/vlc/natty

« back to all changes in this revision

Viewing changes to modules/access/file.c

  • Committer: Bazaar Package Importer
  • Author(s): Benjamin Drung
  • Date: 2010-06-25 01:09:16 UTC
  • mfrom: (1.1.30 upstream)
  • Revision ID: james.westby@ubuntu.com-20100625010916-asxhep2mutg6g6pd
Tags: 1.1.0-1ubuntu1
* Merge from Debian unstable, remaining changes:
  - build and install the libx264 plugin
  - add Xb-Npp header to vlc package
  - Add apport hook to include more vlc dependencies in bug reports
* Drop xulrunner patches.
* Drop 502_xulrunner_191.diff.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
 *****************************************************************************
4
4
 * Copyright (C) 2001-2006 the VideoLAN team
5
5
 * Copyright © 2006-2007 Rémi Denis-Courmont
6
 
 * $Id: ad111cb458c35af33a8accb6c172dc4ae7ffad13 $
 
6
 * $Id: cf3deb26aa0c2e39d286e3c417c563350510ae35 $
7
7
 *
8
8
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
9
9
 *          Rémi Denis-Courmont <rem # videolan # org>
23
23
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
24
24
 *****************************************************************************/
25
25
 
26
 
/*****************************************************************************
27
 
 * Preamble
28
 
 *****************************************************************************/
29
26
#ifdef HAVE_CONFIG_H
30
27
# include "config.h"
31
28
#endif
32
29
 
33
30
#include <vlc_common.h>
34
 
#include <vlc_plugin.h>
 
31
#include "fs.h"
35
32
#include <vlc_input.h>
36
33
#include <vlc_access.h>
37
34
#include <vlc_dialog.h>
38
35
 
39
36
#include <assert.h>
40
37
#include <errno.h>
41
 
#ifdef HAVE_SYS_TYPES_H
42
 
#   include <sys/types.h>
43
 
#endif
 
38
#include <sys/types.h>
44
39
#ifdef HAVE_SYS_STAT_H
45
40
#   include <sys/stat.h>
46
41
#endif
47
42
#ifdef HAVE_FCNTL_H
48
43
#   include <fcntl.h>
49
44
#endif
50
 
#if defined (__linux__)
 
45
#ifdef HAVE_FSTATVFS
 
46
#   include <sys/statvfs.h>
 
47
#   if defined (HAVE_SYS_MOUNT_H)
 
48
#      include <sys/param.h>
 
49
#      include <sys/mount.h>
 
50
#   endif
 
51
#endif
 
52
#ifdef HAVE_LINUX_MAGIC_H
51
53
#   include <sys/vfs.h>
52
54
#   include <linux/magic.h>
53
 
#elif defined (HAVE_SYS_MOUNT_H)
54
 
#   include <sys/param.h>
55
 
#   include <sys/mount.h>
56
55
#endif
57
56
 
58
57
#if defined( WIN32 )
61
60
#   include <shlwapi.h>
62
61
#else
63
62
#   include <unistd.h>
64
 
#   include <poll.h>
65
63
#endif
 
64
#include <dirent.h>
66
65
 
67
66
#if defined( WIN32 ) && !defined( UNDER_CE )
68
67
#   ifdef lseek
71
70
#   define lseek _lseeki64
72
71
#elif defined( UNDER_CE )
73
72
/* FIXME the commandline on wince is a mess */
74
 
# define dup(a) -1
75
73
# define PathIsNetworkPathW(wpath) (! wcsncmp(wpath, L"\\\\", 2))
76
74
#endif
77
75
 
78
 
#include <vlc_charset.h>
79
 
 
80
 
/*****************************************************************************
81
 
 * Module descriptor
82
 
 *****************************************************************************/
83
 
static int  Open ( vlc_object_t * );
84
 
static void Close( vlc_object_t * );
85
 
 
86
 
#define CACHING_TEXT N_("Caching value in ms")
87
 
#define CACHING_LONGTEXT N_( \
88
 
    "Caching value for files. This " \
89
 
    "value should be set in milliseconds." )
90
 
 
91
 
vlc_module_begin ()
92
 
    set_description( N_("File input") )
93
 
    set_shortname( N_("File") )
94
 
    set_category( CAT_INPUT )
95
 
    set_subcategory( SUBCAT_INPUT_ACCESS )
96
 
    add_integer( "file-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, true )
97
 
        change_safe()
98
 
    add_obsolete_string( "file-cat" )
99
 
    set_capability( "access", 50 )
100
 
    add_shortcut( "file" )
101
 
    add_shortcut( "fd" )
102
 
    add_shortcut( "stream" )
103
 
    set_callbacks( Open, Close )
104
 
vlc_module_end ()
105
 
 
106
 
 
107
 
/*****************************************************************************
108
 
 * Exported prototypes
109
 
 *****************************************************************************/
110
 
static int  Seek( access_t *, int64_t );
111
 
static int  NoSeek( access_t *, int64_t );
112
 
static ssize_t Read( access_t *, uint8_t *, size_t );
113
 
static int  Control( access_t *, int, va_list );
114
 
 
115
 
static int  open_file( access_t *, const char * );
 
76
#include <vlc_fs.h>
 
77
#include <vlc_url.h>
116
78
 
117
79
struct access_sys_t
118
80
{
121
83
    int fd;
122
84
 
123
85
    /* */
 
86
    unsigned caching;
124
87
    bool b_pace_control;
125
88
};
126
89
 
 
90
#ifndef WIN32
127
91
static bool IsRemote (int fd)
128
92
{
129
 
#ifdef HAVE_FSTATFS
 
93
#if defined (HAVE_FSTATVFS) && defined (MNT_LOCAL)
 
94
    struct statvfs stf;
 
95
 
 
96
    if (fstatvfs (fd, &stf))
 
97
        return false;
 
98
    /* fstatvfs() is in POSIX, but MNT_LOCAL is not */
 
99
    return !(s.f_flag & MNT_LOCAL);
 
100
 
 
101
#elif defined (HAVE_LINUX_MAGIC_H)
130
102
    struct statfs stf;
131
103
 
132
104
    if (fstatfs (fd, &stf))
133
105
        return false;
134
106
 
135
 
#if defined(MNT_LOCAL)
136
 
    return !(stf.f_flags & MNT_LOCAL);
137
 
 
138
 
#elif defined (__linux__)
139
107
    switch (stf.f_type)
140
108
    {
141
109
        case AFS_SUPER_MAGIC:
148
116
    }
149
117
    return false;
150
118
 
151
 
#endif
152
 
#else /* !HAVE_FSTATFS */
 
119
#else
 
120
    (void)fd;
153
121
    return false;
154
122
 
155
123
#endif
156
124
}
 
125
#endif
157
126
 
 
127
#ifndef HAVE_POSIX_FADVISE
 
128
# define posix_fadvise(fd, off, len, adv)
 
129
#endif
158
130
 
159
131
/*****************************************************************************
160
132
 * Open: open the file
161
133
 *****************************************************************************/
162
 
static int Open( vlc_object_t *p_this )
 
134
int Open( vlc_object_t *p_this )
163
135
{
164
136
    access_t     *p_access = (access_t*)p_this;
165
 
    access_sys_t *p_sys;
 
137
    const char   *path = p_access->psz_path;
166
138
#ifdef WIN32
167
 
    wchar_t wpath[MAX_PATH+1];
168
139
    bool is_remote = false;
169
140
#endif
170
141
 
171
 
    /* Update default_pts to a suitable value for file access */
172
 
    var_Create( p_access, "file-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
173
 
 
174
 
    STANDARD_READ_ACCESS_INIT;
175
 
    p_sys->i_nb_reads = 0;
176
 
    p_sys->b_pace_control = true;
177
 
 
178
142
    /* Open file */
179
143
    int fd = -1;
180
144
 
181
145
    if (!strcasecmp (p_access->psz_access, "fd"))
182
 
        fd = dup (atoi (p_access->psz_path));
183
 
    else if (!strcmp (p_access->psz_path, "-"))
184
 
        fd = dup (0);
 
146
    {
 
147
        char *end;
 
148
        int oldfd = strtol (path, &end, 10);
 
149
 
 
150
        if (*end == '\0')
 
151
            fd = vlc_dup (oldfd);
 
152
        else if (*end == '/' && end > path)
 
153
        {
 
154
            char *name = decode_URI_duplicate (end - 1);
 
155
            if (name != NULL)
 
156
            {
 
157
                name[0] = '.';
 
158
                fd = vlc_openat (oldfd, name, O_RDONLY | O_NONBLOCK);
 
159
                free (name);
 
160
            }
 
161
        }
 
162
    }
185
163
    else
186
164
    {
187
 
        msg_Dbg (p_access, "opening file `%s'", p_access->psz_path);
188
 
        fd = open_file (p_access, p_access->psz_path);
 
165
        msg_Dbg (p_access, "opening file `%s'", path);
 
166
        fd = vlc_open (path, O_RDONLY | O_NONBLOCK);
 
167
        if (fd == -1)
 
168
        {
 
169
            msg_Err (p_access, "cannot open file %s (%m)", path);
 
170
            dialog_Fatal (p_access, _("File reading failed"),
 
171
                          _("VLC could not open the file \"%s\"."), path);
 
172
        }
 
173
 
189
174
#ifdef WIN32
190
 
        if (MultiByteToWideChar (CP_UTF8, 0, p_access->psz_path, -1,
 
175
        wchar_t wpath[MAX_PATH+1];
 
176
        if (MultiByteToWideChar (CP_UTF8, 0, path, -1,
191
177
                                 wpath, MAX_PATH)
192
178
         && PathIsNetworkPathW (wpath))
193
179
            is_remote = true;
195
181
#endif
196
182
    }
197
183
    if (fd == -1)
198
 
        goto error;
 
184
        return VLC_EGENERIC;
199
185
 
200
 
#ifdef HAVE_SYS_STAT_H
201
186
    struct stat st;
202
 
 
203
187
    if (fstat (fd, &st))
204
188
    {
205
189
        msg_Err (p_access, "failed to read (%m)");
209
193
     * how to parse the data. The directory plugin will do it. */
210
194
    if (S_ISDIR (st.st_mode))
211
195
    {
 
196
#ifdef HAVE_FDOPENDIR
 
197
        DIR *handle = fdopendir (fd);
 
198
        if (handle == NULL)
 
199
            goto error; /* Uh? */
 
200
        return DirInit (p_access, handle);
 
201
#else
212
202
        msg_Dbg (p_access, "ignoring directory");
213
203
        goto error;
 
204
#endif
214
205
    }
 
206
 
 
207
    access_sys_t *p_sys = malloc (sizeof (*p_sys));
 
208
    if (unlikely(p_sys == NULL))
 
209
        goto error;
 
210
    access_InitFields (p_access);
 
211
    p_access->pf_read = FileRead;
 
212
    p_access->pf_block = NULL;
 
213
    p_access->pf_control = FileControl;
 
214
    p_access->pf_seek = FileSeek;
 
215
    p_access->p_sys = p_sys;
 
216
    p_sys->i_nb_reads = 0;
 
217
    p_sys->fd = fd;
 
218
    p_sys->caching = var_CreateGetInteger (p_access, "file-caching");
 
219
    if (IsRemote(fd))
 
220
        p_sys->caching += var_CreateGetInteger (p_access, "network-caching");
 
221
    p_sys->b_pace_control = true;
 
222
 
215
223
    if (S_ISREG (st.st_mode))
216
224
        p_access->info.i_size = st.st_size;
217
225
    else if (!S_ISBLK (st.st_mode))
219
227
        p_access->pf_seek = NoSeek;
220
228
        p_sys->b_pace_control = strcasecmp (p_access->psz_access, "stream");
221
229
    }
222
 
#else
223
 
# warning File size not known!
 
230
 
 
231
    if (p_access->pf_seek != NoSeek)
 
232
    {
 
233
        /* Demuxers will need the beginning of the file for probing. */
 
234
        posix_fadvise (fd, 0, 4096, POSIX_FADV_WILLNEED);
 
235
        /* In most cases, we only read the file once. */
 
236
        posix_fadvise (fd, 0, 0, POSIX_FADV_NOREUSE);
 
237
#if defined(HAVE_FCNTL)
 
238
        /* We'd rather use any available memory for reading ahead
 
239
         * than for caching what we've already seen/heard */
 
240
# if defined(F_RDAHEAD)
 
241
        fcntl (fd, F_RDAHEAD, 1);
 
242
# endif
 
243
# if defined(F_NOCACHE)
 
244
        fcntl (fd, F_NOCACHE, 1);
 
245
# endif
224
246
#endif
225
 
 
226
 
    if (IsRemote(fd))
227
 
    {
228
 
        int i_cache = var_GetInteger (p_access, "file-caching") + 700;
229
 
        var_SetInteger (p_access, "file-caching", i_cache);
230
 
        msg_Warn (p_access, "Opening remote file, increasing cache: %d",
231
 
                  i_cache);
232
247
    }
233
 
 
234
 
    p_sys->fd = fd;
235
248
    return VLC_SUCCESS;
236
249
 
237
250
error:
238
 
    if (fd != -1)
239
 
        close (fd);
240
 
    free (p_sys);
 
251
    close (fd);
241
252
    return VLC_EGENERIC;
242
253
}
243
254
 
244
255
/*****************************************************************************
245
256
 * Close: close the target
246
257
 *****************************************************************************/
247
 
static void Close (vlc_object_t * p_this)
 
258
void Close (vlc_object_t * p_this)
248
259
{
249
260
    access_t     *p_access = (access_t*)p_this;
 
261
 
 
262
    if (p_access->pf_read == NULL)
 
263
    {
 
264
        DirClose (p_this);
 
265
        return;
 
266
    }
 
267
 
250
268
    access_sys_t *p_sys = p_access->p_sys;
251
269
 
252
270
    close (p_sys->fd);
259
277
/*****************************************************************************
260
278
 * Read: standard read on a file descriptor.
261
279
 *****************************************************************************/
262
 
static ssize_t Read( access_t *p_access, uint8_t *p_buffer, size_t i_len )
 
280
ssize_t FileRead( access_t *p_access, uint8_t *p_buffer, size_t i_len )
263
281
{
264
282
    access_sys_t *p_sys = p_access->p_sys;
265
283
    int fd = p_sys->fd;
295
313
 
296
314
    p_sys->i_nb_reads++;
297
315
 
298
 
#ifdef HAVE_SYS_STAT_H
299
316
    if ((p_access->info.i_size && !(p_sys->i_nb_reads % INPUT_FSTAT_NB_READS))
300
317
     || (p_access->info.i_pos > p_access->info.i_size))
301
318
    {
 
319
#ifdef HAVE_SYS_STAT_H
302
320
        struct stat st;
303
321
 
304
322
        if ((fstat (fd, &st) == 0)
305
 
         && (p_access->info.i_size != st.st_size))
 
323
         && (p_access->info.i_size != (uint64_t)st.st_size))
306
324
        {
307
325
            p_access->info.i_size = st.st_size;
308
326
            p_access->info.i_update |= INPUT_UPDATE_SIZE;
309
327
        }
 
328
#endif
310
329
    }
311
 
#endif
312
330
    return i_ret;
313
331
}
314
332
 
316
334
/*****************************************************************************
317
335
 * Seek: seek to a specific location in a file
318
336
 *****************************************************************************/
319
 
static int Seek (access_t *p_access, int64_t i_pos)
 
337
int FileSeek (access_t *p_access, uint64_t i_pos)
320
338
{
321
339
    p_access->info.i_pos = i_pos;
322
340
    p_access->info.b_eof = false;
325
343
    return VLC_SUCCESS;
326
344
}
327
345
 
328
 
static int NoSeek (access_t *p_access, int64_t i_pos)
 
346
int NoSeek (access_t *p_access, uint64_t i_pos)
329
347
{
330
348
    /* assert(0); ?? */
331
349
    (void) p_access; (void) i_pos;
335
353
/*****************************************************************************
336
354
 * Control:
337
355
 *****************************************************************************/
338
 
static int Control( access_t *p_access, int i_query, va_list args )
 
356
int FileControl( access_t *p_access, int i_query, va_list args )
339
357
{
340
358
    access_sys_t *p_sys = p_access->p_sys;
341
359
    bool    *pb_bool;
359
377
        /* */
360
378
        case ACCESS_GET_PTS_DELAY:
361
379
            pi_64 = (int64_t*)va_arg( args, int64_t * );
362
 
            *pi_64 = var_GetInteger( p_access, "file-caching" ) * INT64_C(1000);
 
380
            *pi_64 = p_sys->caching * INT64_C(1000);
363
381
            break;
364
382
 
365
383
        /* */
383
401
    }
384
402
    return VLC_SUCCESS;
385
403
}
386
 
 
387
 
/*****************************************************************************
388
 
 * open_file: Opens a specific file
389
 
 *****************************************************************************/
390
 
static int open_file (access_t *p_access, const char *path)
391
 
{
392
 
#if defined(WIN32)
393
 
    if (!strcasecmp (p_access->psz_access, "file")
394
 
      && ('/' == path[0]) && isalpha (path[1])
395
 
      && (':' == path[2]) && ('/' == path[3]))
396
 
        /* Explorer can open path such as file:/C:/ or file:///C:/
397
 
         * hence remove leading / if found */
398
 
        path++;
399
 
#endif
400
 
 
401
 
    int fd = utf8_open (path, O_RDONLY | O_NONBLOCK /* O_LARGEFILE*/, 0666);
402
 
    if (fd == -1)
403
 
    {
404
 
        msg_Err (p_access, "cannot open file %s (%m)", path);
405
 
        dialog_Fatal (p_access, _("File reading failed"),
406
 
                      _("VLC could not open the file \"%s\"."), path);
407
 
        return -1;
408
 
    }
409
 
 
410
 
#if defined(HAVE_FCNTL)
411
 
    /* We'd rather use any available memory for reading ahead
412
 
     * than for caching what we've already seen/heard */
413
 
# if defined(F_RDAHEAD)
414
 
    fcntl (fd, F_RDAHEAD, 1);
415
 
# endif
416
 
# if defined(F_NOCACHE)
417
 
    fcntl (fd, F_NOCACHE, 1);
418
 
# endif
419
 
#endif
420
 
 
421
 
    return fd;
422
 
}