file.c 17.9 KB
Newer Older
1
2
3
/*****************************************************************************
 * file.c: file input (file: access plug-in)
 *****************************************************************************
4
 * Copyright (C) 2001-2006 the VideoLAN team
gbazin's avatar
gbazin committed
5
 * $Id$
6
7
 *
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
8
 *          Rémi Denis-Courmont <rem # videolan # org>
9
10
11
12
13
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
14
 *
15
16
17
18
19
20
21
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
dionoea's avatar
dionoea committed
22
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23
24
25
26
27
28
29
 *****************************************************************************/

/*****************************************************************************
 * Preamble
 *****************************************************************************/
#include <vlc/vlc.h>
#include <vlc/input.h>
30
#include <vlc_interaction.h>
31

32
33
#include <stdlib.h>
#include <string.h>
34
#include <errno.h>
35
36
37
38
39
40
41
42
43
44
#ifdef HAVE_SYS_TYPES_H
#   include <sys/types.h>
#endif
#ifdef HAVE_SYS_STAT_H
#   include <sys/stat.h>
#endif
#ifdef HAVE_FCNTL_H
#   include <fcntl.h>
#endif

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
45
46
47
#if defined( WIN32 ) && !defined( UNDER_CE )
#   include <io.h>
#else
48
#   include <unistd.h>
49
#   include <poll.h>
50
51
#endif

gbazin's avatar
   
gbazin committed
52
#if defined( WIN32 ) && !defined( UNDER_CE )
53
/* fstat() support for large files on win32 */
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
#   define fstat(a,b) _fstati64(a,b)
#   ifdef lseek
#      undef lseek
#   endif
#   define lseek _lseeki64
#elif defined( UNDER_CE )
#   ifdef read
#      undef read
#   endif
#   define read(a,b,c) fread(b,1,c,a)
#   define close(a) fclose(a)
#   ifdef lseek
#      undef lseek
#   endif
#   define lseek fseek
gbazin's avatar
gbazin committed
69
70
#endif

71
72
#include "charset.h"

73
74
75
/*****************************************************************************
 * Module descriptor
 *****************************************************************************/
76
77
78
static int  Open ( vlc_object_t * );
static void Close( vlc_object_t * );

Christophe Massiot's avatar
Christophe Massiot committed
79
#define CACHING_TEXT N_("Caching value in ms")
gbazin's avatar
   
gbazin committed
80
#define CACHING_LONGTEXT N_( \
81
    "Caching value for files. This " \
zorglub's avatar
zorglub committed
82
    "value should be set in milliseconds." )
gbazin's avatar
gbazin committed
83
84
#define CAT_TEXT N_("Concatenate with additional files")
#define CAT_LONGTEXT N_( \
zorglub's avatar
zorglub committed
85
86
    "Play split files as if they were part of a unique file. " \
    "You need to specify a comma-separated list of files." )
gbazin's avatar
   
gbazin committed
87

88
vlc_module_begin();
zorglub's avatar
zorglub committed
89
    set_description( _("File input") );
zorglub's avatar
zorglub committed
90
    set_shortname( _("File") );
zorglub's avatar
zorglub committed
91
92
    set_category( CAT_INPUT );
    set_subcategory( SUBCAT_INPUT_ACCESS );
93
    add_integer( "file-caching", DEFAULT_PTS_DELAY / 1000, NULL, CACHING_TEXT, CACHING_LONGTEXT, VLC_TRUE );
gbazin's avatar
gbazin committed
94
    add_string( "file-cat", NULL, NULL, CAT_TEXT, CAT_LONGTEXT, VLC_TRUE );
95
    set_capability( "access2", 50 );
96
97
    add_shortcut( "file" );
    add_shortcut( "stream" );
98
    add_shortcut( "kfir" );
99
100
    set_callbacks( Open, Close );
vlc_module_end();
101
102


103
/*****************************************************************************
104
 * Exported prototypes
105
 *****************************************************************************/
106
107
108
109
static int  Seek( access_t *, int64_t );
static int  Read( access_t *, uint8_t *, int );
static int  Control( access_t *, int, va_list );

110
static int  _OpenFile( access_t *, const char * );
111
112

typedef struct
gbazin's avatar
gbazin committed
113
114
115
116
117
118
{
    char     *psz_name;
    int64_t  i_size;

} file_entry_t;

119
struct access_sys_t
120
{
121
122
    unsigned int i_nb_reads;
    vlc_bool_t   b_kfir;
gbazin's avatar
gbazin committed
123
124

    /* Files list */
125
126
    int          i_file;
    file_entry_t **file;
gbazin's avatar
gbazin committed
127
128
129

    /* Current file */
    int  i_index;
130
#ifndef UNDER_CE
131
    int  fd;
132
133
134
135
    int  fd_backup;
#else
    FILE *fd;
    FILE *fd_backup;
136
#endif
gbazin's avatar
gbazin committed
137

138
139
140
141
    /* */
    vlc_bool_t b_seekable;
    vlc_bool_t b_pace_control;
};
142

143
144
145
146
147
/*****************************************************************************
 * Open: open the file
 *****************************************************************************/
static int Open( vlc_object_t *p_this )
{
148
149
    access_t     *p_access = (access_t*)p_this;
    access_sys_t *p_sys;
150
    char *psz_name = strdup( p_access->psz_path );
151

152
#ifdef HAVE_SYS_STAT_H
153
    struct stat         stat_info;
154
#endif
gbazin's avatar
gbazin committed
155
    file_entry_t *      p_file;
156
    vlc_bool_t          b_stdin = psz_name[0] == '-' && psz_name[1] == '\0';
157

158
    if( !b_stdin )
159
    {
160
161
        if( psz_name[0] == '~' && psz_name[1] == '/' )
        {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
162
163
           char *psz;

164
165
            /* This is incomplete : we should also support the ~cmassiot/
             * syntax. */
166
            asprintf( &psz, "%s/%s", p_access->p_libvlc->psz_homedir, psz_name + 2 );
167
168
169
            free( psz_name );
            psz_name = psz;
        }
170
171
172
173
174
175
176
177
178
#if defined(WIN32)
        else if( !strcasecmp( p_access->psz_access, "file" )
                && ('/' == psz_name[0]) && psz_name[1]
                && (':' == psz_name[2]) && ('/' == psz_name[3]) )
        {
            /*
            ** explorer can open path such as file:/C:/ or file:///C:/...
            ** hence remove leading / if found
            */
179
            strcpy( psz_name, p_access->psz_path + 1 );
180
181
        }
#endif
182
    }
183

184
    STANDARD_READ_ACCESS_INIT;
185
186
187
188
189
    p_sys->i_nb_reads = 0;
    p_sys->b_kfir = VLC_FALSE;
    p_sys->file = NULL;
    p_sys->i_file = 0;
    p_sys->i_index = 0;
190
#ifndef UNDER_CE
191
    p_sys->fd = -1;
192
#endif
193

194
195
196
197
198
199
200
201
202
    msg_Dbg( p_access, "opening file `%s'", psz_name );

    if( b_stdin )
        p_sys->fd = dup(0);
    else
        _OpenFile( p_access, psz_name );

    if( p_sys->fd == -1 )
    {
Rafaël Carré's avatar
Rafaël Carré committed
203
        free( psz_name );
204
205
206
207
208
209
210
211
212
        free( p_sys );
        return VLC_EGENERIC;
    }

#ifdef HAVE_SYS_STAT_H
    if( fstat( p_sys->fd, &stat_info ) )
    {
        msg_Err( p_access, "%s: %s", p_access->psz_path, strerror( errno ) );
        close( p_sys->fd );
Rafaël Carré's avatar
Rafaël Carré committed
213
        free( psz_name );
214
215
216
217
218
        free( p_sys );
        return VLC_EGENERIC;
    }
#endif

219
    if( !strcasecmp( p_access->psz_access, "stream" ) )
220
    {
221
222
        p_sys->b_seekable = VLC_FALSE;
        p_sys->b_pace_control = VLC_FALSE;
223
    }
224
    else if( !strcasecmp( p_access->psz_access, "kfir" ) )
225
    {
226
227
228
        p_sys->b_seekable = VLC_FALSE;
        p_sys->b_pace_control = VLC_FALSE;
        p_sys->b_kfir = VLC_TRUE;
229
    }
230
231
232
    else
    {
        /* file:%s or %s */
233
        p_sys->b_pace_control = VLC_TRUE;
234
235

        if( b_stdin )
236
            p_sys->b_seekable = VLC_FALSE;
237
238
239
        else
#if defined( HAVE_SYS_STAT_H )
        if( S_ISREG(stat_info.st_mode) || S_ISBLK(stat_info.st_mode)
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
240
         || ( S_ISCHR(stat_info.st_mode) && (stat_info.st_size > 0) ) )
241
        {
242
243
            p_sys->b_seekable = VLC_TRUE;
            p_access->info.i_size = stat_info.st_size;
244
        }
245
        else
246
            p_sys->b_seekable = VLC_FALSE;
247
248
249
#else
            /* We'll update i_size after it's been opened */
            p_sys->b_seekable = VLC_TRUE;
250
#endif
251
252
    }

253
    if( p_sys->b_seekable && !p_access->info.i_size )
254
    {
255
256
        /* FIXME that's bad because all others access will be probed */
        msg_Err( p_access, "file %s is empty, aborting", psz_name );
257
        close( p_sys->fd );
258
        free( p_sys );
Rafaël Carré's avatar
Rafaël Carré committed
259
        free( psz_name );
260
261
262
        return VLC_EGENERIC;
    }

gbazin's avatar
   
gbazin committed
263
    /* Update default_pts to a suitable value for file access */
264
    var_Create( p_access, "file-caching", VLC_VAR_INTEGER | VLC_VAR_DOINHERIT );
gbazin's avatar
   
gbazin committed
265

gbazin's avatar
gbazin committed
266
267
268
    /*
     * Get the additional list of files
     */
269
270
    p_file = malloc( sizeof(file_entry_t) );
    p_file->i_size = p_access->info.i_size;
271
    p_file->psz_name = psz_name;
272
    TAB_APPEND( p_sys->i_file, p_sys->file, p_file );
gbazin's avatar
gbazin committed
273

Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
274
275
    psz_name = var_CreateGetString( p_access, "file-cat" );
    if( *psz_name )
gbazin's avatar
gbazin committed
276
    {
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
277
        char *psz_parser = psz_name;
gbazin's avatar
gbazin committed
278
279
280
281
282
283
284
285
286
287
        int64_t i_size;

        while( psz_name && *psz_name )
        {
            psz_parser = strchr( psz_name, ',' );
            if( psz_parser ) *psz_parser = 0;

            psz_name = strdup( psz_name );
            if( psz_name )
            {
288
                msg_Dbg( p_access, "adding file `%s'", psz_name );
289
                i_size = 0;
gbazin's avatar
gbazin committed
290
291
292
293

#ifdef HAVE_SYS_STAT_H
                if( !stat( psz_name, &stat_info ) )
                {
294
                    p_access->info.i_size += stat_info.st_size;
gbazin's avatar
gbazin committed
295
296
297
298
                    i_size = stat_info.st_size;
                }
                else
                {
299
                    msg_Dbg( p_access, "cannot stat() file `%s'", psz_name );
gbazin's avatar
gbazin committed
300
301
                }
#endif
302
                p_file = malloc( sizeof(file_entry_t) );
gbazin's avatar
gbazin committed
303
304
305
                p_file->i_size = i_size;
                p_file->psz_name = psz_name;

306
                TAB_APPEND( p_sys->i_file, p_sys->file, p_file );
gbazin's avatar
gbazin committed
307
308
309
310
311
312
            }

            psz_name = psz_parser;
            if( psz_name ) psz_name++;
        }
    }
Rémi Denis-Courmont's avatar
Rémi Denis-Courmont committed
313
    free( psz_name );
gbazin's avatar
gbazin committed
314

315
    return VLC_SUCCESS;
316
317
318
}

/*****************************************************************************
319
 * Close: close the target
320
 *****************************************************************************/
321
322
static void Close( vlc_object_t * p_this )
{
323
324
    access_t     *p_access = (access_t*)p_this;
    access_sys_t *p_sys = p_access->p_sys;
gbazin's avatar
gbazin committed
325
    int i;
326

327
    close( p_sys->fd );
gbazin's avatar
gbazin committed
328

329
    for( i = 0; i < p_sys->i_file; i++ )
gbazin's avatar
gbazin committed
330
    {
331
332
        free( p_sys->file[i]->psz_name );
        free( p_sys->file[i] );
gbazin's avatar
gbazin committed
333
    }
334
    free( p_sys->file );
335

336
    free( p_sys );
337
338
339
340
341
}

/*****************************************************************************
 * Read: standard read on a file descriptor.
 *****************************************************************************/
342
static int Read( access_t *p_access, uint8_t *p_buffer, int i_len )
343
{
344
345
346
    access_sys_t *p_sys = p_access->p_sys;
    int i_ret;

347
#if !defined(WIN32) && !defined(UNDER_CE)
348
    if( !p_sys->b_pace_control )
349
    {
350
        if( !p_sys->b_kfir )
351
        {
352
            /* Find if some data is available. This won't work under Windows. */
353
            do
354
            {
355
                struct pollfd ufd;
356

357
                if( p_access->b_die )
358
359
                    return 0;

360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
                memset (&ufd, 0, sizeof (ufd));
                ufd.fd = p_sys->fd;
                ufd.events = POLLIN;

                i_ret = poll( &ufd, 1, 500 );
                if( i_ret == -1 )
                {
                    if( errno != EINTR )
                    {
                        msg_Err( p_access, "poll error: %s",
                                 strerror( errno ) );
                        return -1;
                    }
                    i_ret = 0;
                }
375
            }
376
            while( i_ret == 0 );
377

378
            i_ret = read( p_sys->fd, p_buffer, i_len );
379
380
        }
        else
381
        {
382
            /* b_kfir ; work around a buggy poll() driver implementation */
383
384
            while ( (i_ret = read( p_sys->fd, p_buffer, i_len )) == 0 &&
                    !p_access->b_die )
385
            {
386
                msleep( INPUT_ERROR_SLEEP );
387
            }
388
389
        }
    }
390
    else
391
#endif /* WIN32 || UNDER_CE */
392
393
    {
        /* b_pace_control || WIN32 */
394
        i_ret = read( p_sys->fd, p_buffer, i_len );
395
    }
396

397
398
    if( i_ret < 0 )
    {
399
        if( errno != EINTR && errno != EAGAIN )
400
        {
401
            msg_Err( p_access, "read failed (%s)", strerror(errno) );
402
403
404
405
            intf_UserFatal( p_access, VLC_FALSE, _("File reading failed"), 
                            _("VLC could not read file \"%s\"."),
                            strerror(errno) );
        }
406
407
408
409

        /* Delay a bit to avoid consuming all the CPU. This is particularly
         * useful when reading from an unconnected FIFO. */
        msleep( INPUT_ERROR_SLEEP );
410
    }
411
412

    p_sys->i_nb_reads++;
413
#ifdef HAVE_SYS_STAT_H
414
415
    if( p_access->info.i_size != 0 &&
        (p_sys->i_nb_reads % INPUT_FSTAT_NB_READS) == 0 )
416
417
    {
        struct stat stat_info;
418
        int i_file = p_sys->i_index;
gbazin's avatar
gbazin committed
419

420
        if ( fstat( p_sys->fd, &stat_info ) == -1 )
421
        {
422
            msg_Warn( p_access, "couldn't stat again the file (%s)", strerror(errno) );
423
        }
424
        else if ( p_sys->file[i_file]->i_size != stat_info.st_size )
425
        {
426
            p_access->info.i_size += (stat_info.st_size - p_sys->file[i_file]->i_size );
427
            p_sys->file[i_file]->i_size = stat_info.st_size;
428
            p_access->info.i_update |= INPUT_UPDATE_SIZE;
429
430
431
432
        }
    }
#endif

gbazin's avatar
gbazin committed
433
    /* If we reached an EOF then switch to the next file in the list */
434
    if ( i_ret == 0 && p_sys->i_index + 1 < p_sys->i_file )
gbazin's avatar
gbazin committed
435
    {
436
        char *psz_name = p_sys->file[++p_sys->i_index]->psz_name;
437
        p_sys->fd_backup = p_sys->fd;
gbazin's avatar
gbazin committed
438

439
        msg_Dbg( p_access, "opening file `%s'", psz_name );
gbazin's avatar
gbazin committed
440

441
        if ( _OpenFile( p_access, psz_name ) )
442
        {
443
            p_sys->fd = p_sys->fd_backup;
444
445
            return 0;
        }
gbazin's avatar
gbazin committed
446

447
        close( p_sys->fd_backup );
gbazin's avatar
gbazin committed
448
449

        /* We have to read some data */
450
        return Read( p_access, p_buffer, i_len );
gbazin's avatar
gbazin committed
451
452
    }

453
454
455
456
457
    if( i_ret > 0 )
        p_access->info.i_pos += i_ret;
    else if( i_ret == 0 )
        p_access->info.b_eof = VLC_TRUE;

458
459
460
461
462
463
    return i_ret;
}

/*****************************************************************************
 * Seek: seek to a specific location in a file
 *****************************************************************************/
464
static int Seek( access_t *p_access, int64_t i_pos )
465
{
466
    access_sys_t *p_sys = p_access->p_sys;
gbazin's avatar
gbazin committed
467
468
469
    int64_t i_size = 0;

    /* Check which file we need to access */
470
    if( p_sys->i_file > 1 )
gbazin's avatar
gbazin committed
471
    {
472
473
        int i;
        char *psz_name;
474
        p_sys->fd_backup = p_sys->fd;
gbazin's avatar
gbazin committed
475

476
        for( i = 0; i < p_sys->i_file - 1; i++ )
gbazin's avatar
gbazin committed
477
        {
478
479
480
            if( i_pos < p_sys->file[i]->i_size + i_size )
                break;
            i_size += p_sys->file[i]->i_size;
gbazin's avatar
gbazin committed
481
        }
482
        psz_name = p_sys->file[i]->psz_name;
gbazin's avatar
gbazin committed
483

484
        msg_Dbg( p_access, "opening file `%s'", psz_name );
gbazin's avatar
gbazin committed
485

486
        if ( i != p_sys->i_index && !_OpenFile( p_access, psz_name ) )
gbazin's avatar
gbazin committed
487
488
        {
            /* Close old file */
489
            close( p_sys->fd_backup );
490
            p_sys->i_index = i;
gbazin's avatar
gbazin committed
491
492
493
        }
        else
        {
494
            p_sys->fd = p_sys->fd_backup;
gbazin's avatar
gbazin committed
495
496
        }
    }
497

498
    lseek( p_sys->fd, i_pos - i_size, SEEK_SET );
499

500
501
    p_access->info.i_pos = i_pos;
    if( p_access->info.i_size < p_access->info.i_pos )
502
    {
503
504
        msg_Err( p_access, "seeking too far" );
        p_access->info.i_pos = p_access->info.i_size;
505
    }
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
    else if( p_access->info.i_pos < 0 )
    {
        msg_Err( p_access, "seeking too early" );
        p_access->info.i_pos = 0;
    }
    /* Reset eof */
    p_access->info.b_eof = VLC_FALSE;

    /* FIXME */
    return VLC_SUCCESS;
}

/*****************************************************************************
 * Control:
 *****************************************************************************/
static int Control( access_t *p_access, int i_query, va_list args )
{
    access_sys_t *p_sys = p_access->p_sys;
    vlc_bool_t   *pb_bool;
    int          *pi_int;
    int64_t      *pi_64;

    switch( i_query )
529
    {
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
        /* */
        case ACCESS_CAN_SEEK:
        case ACCESS_CAN_FASTSEEK:
            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
            *pb_bool = p_sys->b_seekable;
            break;

        case ACCESS_CAN_PAUSE:
        case ACCESS_CAN_CONTROL_PACE:
            pb_bool = (vlc_bool_t*)va_arg( args, vlc_bool_t* );
            *pb_bool = p_sys->b_pace_control;
            break;

        /* */
        case ACCESS_GET_MTU:
            pi_int = (int*)va_arg( args, int * );
            *pi_int = 0;
            break;

        case ACCESS_GET_PTS_DELAY:
            pi_64 = (int64_t*)va_arg( args, int64_t * );
551
            *pi_64 = var_GetInteger( p_access, "file-caching" ) * I64C(1000);
552
            break;
553

554
555
556
557
558
559
560
561
        /* */
        case ACCESS_SET_PAUSE_STATE:
            /* Nothing to do */
            break;

        case ACCESS_GET_TITLE_INFO:
        case ACCESS_SET_TITLE:
        case ACCESS_SET_SEEKPOINT:
562
        case ACCESS_SET_PRIVATE_ID_STATE:
563
        case ACCESS_GET_META:
564
565
566
            return VLC_EGENERIC;

        default:
567
            msg_Warn( p_access, "unimplemented query in control" );
568
569
            return VLC_EGENERIC;

570
    }
571
    return VLC_SUCCESS;
572
573
}

574

gbazin's avatar
gbazin committed
575
576
577
/*****************************************************************************
 * OpenFile: Opens a specific file
 *****************************************************************************/
578
static int _OpenFile( access_t * p_access, const char * psz_name )
gbazin's avatar
gbazin committed
579
{
580
    access_sys_t *p_sys = p_access->p_sys;
gbazin's avatar
gbazin committed
581
582

#ifdef UNDER_CE
583
    p_sys->fd = utf8_fopen( psz_name, "rb" );
584
    if ( !p_sys->fd )
gbazin's avatar
gbazin committed
585
    {
586
        msg_Err( p_access, "cannot open file %s", psz_name );
587
588
        intf_UserFatal( p_access, VLC_FALSE, _("File reading failed"), 
                        _("VLC could not open file \"%s\"."), psz_name );
gbazin's avatar
gbazin committed
589
590
        return VLC_EGENERIC;
    }
591
592
593

    fseek( p_sys->fd, 0, SEEK_END );
    p_access->info.i_size = ftell( p_sys->fd );
594
    p_access->info.i_update |= INPUT_UPDATE_SIZE;
595
    fseek( p_sys->fd, 0, SEEK_SET );
gbazin's avatar
gbazin committed
596
#else
597
598
599
600
601
602
    const char *psz_localname = ToLocale( psz_name );
    if( psz_localname == NULL )
    {
        msg_Err( p_access, "incorrect file name %s", psz_name );
        return VLC_EGENERIC;
    }
gbazin's avatar
gbazin committed
603

604
    // FIXME: support non-ANSI filenames on Win32
605
606
    p_sys->fd = open( psz_localname, O_NONBLOCK /*| O_LARGEFILE*/ );
    LocaleFree( psz_localname );
607

608
    if ( p_sys->fd == -1 )
gbazin's avatar
gbazin committed
609
    {
610
        msg_Err( p_access, "cannot open file %s (%s)", psz_name,
gbazin's avatar
gbazin committed
611
                 strerror(errno) );
612
613
614
        intf_UserFatal( p_access, VLC_FALSE, _("File reading failed"), 
                        _("VLC could not open file \"%s\" (%s)."),
                        psz_name, strerror(errno) );
gbazin's avatar
gbazin committed
615
616
        return VLC_EGENERIC;
    }
617

618
#if defined(HAVE_FCNTL_H) && defined(F_FDAHEAD) && defined(F_NOCACHE)
619
620
621
622
623
624
    /* We'd rather use any available memory for reading ahead
     * than for caching what we've already seen/heard */
    fcntl(p_sys->fd, F_RDAHEAD, 1);
    fcntl(p_sys->fd, F_NOCACHE, 1);
#endif

gbazin's avatar
gbazin committed
625
626
627
628
#endif

    return VLC_SUCCESS;
}