Eine aufbereitete Darstellung der Quelle

 
     
 
 
Anforderungen  |   Konzepte  |   Entwurf  |   Entwicklung  |   Qualitätssicherung  |   Lebenszyklus  |   Steuerung
 
 
 
 

Benutzer

Quelle  file.c   Sprache: C

 

/*****************************************************************************
 * file.c: file input (file: access plug-in)
 *****************************************************************************
 * Copyright (C) 2001-2006 VLC authors and VideoLAN
 * Copyright © 2006-2007 Rémi Denis-Courmont
 *
 * Authors: Christophe Massiot <massiot@via.ecp.fr>
 *          Rémi Denis-Courmont
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 *
 * 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 Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
 *****************************************************************************/


#ifdef HAVE_CONFIG_H
# include "config.h"
#endif

#include <assert.h>
#include <errno.h>
#include <limits.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#ifdef HAVE_FSTATVFS
#   include <sys/statvfs.h>
#   if defined (HAVE_SYS_MOUNT_H)
#      include <sys/param.h>
#      include <sys/mount.h>
#   endif
#endif
#ifdef HAVE_LINUX_MAGIC_H
#   include <sys/vfs.h>
#   include <linux/magic.h>
#endif

#if defined( _WIN32 )
#   include <io.h>
#   include <ctype.h>
#else
#   include <unistd.h>
#endif

#include <vlc_common.h>
#include "fs.h"
#include <vlc_access.h>
#include <vlc_interrupt.h>
#ifdef _WIN32
# include <vlc_charset.h>
#endif
#include <vlc_fs.h>
#include <vlc_url.h>

typedef struct
{
    int fd;

    bool b_pace_control;
} access_sys_t;

#if !defined (_WIN32) && !defined (__OS2__)
static bool IsRemote (int fd)
{
#if defined(__APPLE__)
    /* This has to preceed the general fstatvfs implmentation below,
     * as even though Darwin has fstatvfs, it does not expose the
     * MNT_LOCAL in the statvfs.f_flag field.
     */

    struct statfs sfs;

    if (fstatfs (fd, &sfs))
        return false;

    return !((sfs.f_flags & MNT_LOCAL) == MNT_LOCAL);

#elif defined (HAVE_FSTATVFS) && defined (MNT_LOCAL)
    struct statvfs stf;

    if (fstatvfs (fd, &stf))
        return false;
    /* fstatvfs() is in POSIX, but MNT_LOCAL is not */
    return !(stf.f_flag & MNT_LOCAL);

#elif defined (HAVE_LINUX_MAGIC_H)
    struct statfs stf;

    if (fstatfs (fd, &stf))
        return false;

    switch ((unsigned long)stf.f_type)
    {
        case AFS_SUPER_MAGIC:
        case CODA_SUPER_MAGIC:
        case NCP_SUPER_MAGIC:
        case NFS_SUPER_MAGIC:
        case SMB_SUPER_MAGIC:
        case 0xFF534D42 /*CIFS_MAGIC_NUMBER*/:
            return true;
    }
    return false;

#else
    (void)fd;
    return false;

#endif
}
# define IsRemote(fd,path) IsRemote(fd)

#elif defined(_WIN32)

static bool IsRemote(int fd, const char *path)
{
    VLC_UNUSED(fd);

    size_t len = strlen(path);
    if (len < 2)
        return false;
    if (path[0] == '\\' && path[1] == '\\')
        return true;
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP) ||  NTDDI_VERSION >= NTDDI_WIN10_RS3
    if (path[1] == ':')
    {
        char drive[4];
        drive[0] = path[0]; // can only be < 0x80 if second char is ':'
        drive[1] = ':';
        drive[2] = '\\';
        drive[3] = '\0';
        UINT driveType = GetDriveTypeA(drive);
        switch (driveType)
        {
            case DRIVE_FIXED:
            case DRIVE_REMOVABLE: // but a floppy drive is slower than network
            case DRIVE_RAMDISK:
            case DRIVE_CDROM:
                return false;
            default:
                return true;
        }
    }
#endif
    return false;
}

#else /* __OS2__ */

static bool IsRemote (const char *path)
{
    return (! strncmp(path, "\\\\", 2));
}
# define IsRemote(fd,path) IsRemote(path)
#endif

#ifndef HAVE_POSIX_FADVISE
# define posix_fadvise(fd, off, len, adv)
#endif

static ssize_t Read (stream_t *, void *, size_t);
static int FileSeek (stream_t *, uint64_t);
static int FileControl (stream_t *, int, va_list);

/*****************************************************************************
 * FileOpen: open the file
 *****************************************************************************/

int FileOpen( vlc_object_t *p_this )
{
    stream_t *p_access = (stream_t*)p_this;

    /* Open file */
    int fd = -1;

    if (!strcasecmp (p_access->psz_name, "fd"))
    {
        char *end;
        unsigned long oldfd = strtoul(p_access->psz_location, &end, 10);

        if (oldfd > INT_MAX)
            errno = EBADF;
        else if (*end == '\0')
            fd = vlc_dup (oldfd);
        else if (*end == '/' && end > p_access->psz_location)
        {
            char *name = vlc_uri_decode_duplicate (end - 1);
            if (name != NULL)
            {
                name[0] = '.';
                fd = vlc_openat (oldfd, name, O_RDONLY | O_NONBLOCK);
                free (name);
            }
        }
    }
    else
    {
        if (unlikely(p_access->psz_filepath == NULL))
            return VLC_EGENERIC;
        fd = vlc_open (p_access->psz_filepath, O_RDONLY | O_NONBLOCK);
    }

    if (fd == -1)
    {
        msg_Err (p_access, "cannot open file %s (%s)",
                 p_access->psz_filepath ? p_access->psz_filepath
                                        : p_access->psz_location,
                 vlc_strerror_c(errno));
        return VLC_EGENERIC;
    }

    struct stat st;
    if (fstat (fd, &st))
    {
        msg_Err (p_access, "read error: %s", vlc_strerror_c(errno));
        goto error;
    }

#if O_NONBLOCK
    /* Force blocking mode back */
    fcntl (fd, F_SETFL, fcntl (fd, F_GETFL) & ~O_NONBLOCK);
#endif

    /* Directories can be opened and read from, but only readdir() knows
     * how to parse the data. The directory plugin will do it. */

    if (S_ISDIR (st.st_mode))
    {
#ifdef HAVE_FDOPENDIR
        DIR *p_dir = fdopendir(fd);
        if (!p_dir) {
            msg_Err (p_access, "fdopendir error: %s", vlc_strerror_c(errno));
            goto error;
        }
        return DirInit (p_access, p_dir);
#else
        msg_Dbg (p_access, "ignoring directory");
        goto error;
#endif
    }

    access_sys_t *p_sys = vlc_obj_malloc(p_this, sizeof (*p_sys));
    if (unlikely(p_sys == NULL))
        goto error;
    p_access->pf_read = Read;
    p_access->pf_block = NULL;
    p_access->pf_control = FileControl;
    p_access->p_sys = p_sys;
    p_sys->fd = fd;

    if (S_ISREG (st.st_mode) || S_ISBLK (st.st_mode))
    {
        p_access->pf_seek = FileSeek;
        p_sys->b_pace_control = true;

        /* Demuxers will need the beginning of the file for probing. */
        posix_fadvise (fd, 0, 4096, POSIX_FADV_WILLNEED);
        /* In most cases, we only read the file once. */
        posix_fadvise (fd, 0, 0, POSIX_FADV_NOREUSE);
#ifdef F_NOCACHE
        fcntl (fd, F_NOCACHE, 0);
#endif
#ifdef F_RDAHEAD
        if (IsRemote(fd, p_access->psz_filepath))
            fcntl (fd, F_RDAHEAD, 0);
        else
            fcntl (fd, F_RDAHEAD, 1);
#endif
    }
    else
    {
        p_access->pf_seek = NULL;
        p_sys->b_pace_control = strcasecmp (p_access->psz_name, "stream");
    }

    return VLC_SUCCESS;

error:
    vlc_close (fd);
    return VLC_EGENERIC;
}

/*****************************************************************************
 * FileClose: close the target
 *****************************************************************************/

void FileClose (vlc_object_t * p_this)
{
    stream_t     *p_access = (stream_t*)p_this;

    if (p_access->pf_read == NULL)
    {
        DirClose (p_this);
        return;
    }

    access_sys_t *p_sys = p_access->p_sys;

    vlc_close (p_sys->fd);
}


static ssize_t Read (stream_t *p_access, void *p_buffer, size_t i_len)
{
    access_sys_t *p_sys = p_access->p_sys;
    int fd = p_sys->fd;

    ssize_t val = vlc_read_i11e (fd, p_buffer, i_len);
    if (val < 0)
    {
        switch (errno)
        {
            case EINTR:
            case EAGAIN:
                return -1;
        }

        msg_Err (p_access, "read error: %s", vlc_strerror_c(errno));
        val = 0;
    }

    return val;
}

/*****************************************************************************
 * Seek: seek to a specific location in a file
 *****************************************************************************/

static int FileSeek (stream_t *p_access, uint64_t i_pos)
{
    access_sys_t *sys = p_access->p_sys;

    if (lseek(sys->fd, i_pos, SEEK_SET) == (off_t)-1)
        return VLC_EGENERIC;
    return VLC_SUCCESS;
}

/*****************************************************************************
 * Control:
 *****************************************************************************/

static int FileControl( stream_t *p_access, int i_query, va_list args )
{
    access_sys_t *p_sys = p_access->p_sys;
    bool    *pb_bool;
    vlc_tick_t *pi_64;

    switch( i_query )
    {
        case STREAM_CAN_SEEK:
        case STREAM_CAN_FASTSEEK:
            pb_bool = va_arg( args, bool * );
            *pb_bool = (p_access->pf_seek != NULL);
            break;

        case STREAM_CAN_PAUSE:
        case STREAM_CAN_CONTROL_PACE:
            pb_bool = va_arg( args, bool * );
            *pb_bool = p_sys->b_pace_control;
            break;

        case STREAM_CAN_DOWNLOAD:
            pb_bool = va_arg( args, bool * );
            *pb_bool = true;
            break;

        case STREAM_GET_SIZE:
        case STREAM_GET_MTIME:
        {
            struct stat st;

            if (fstat (p_sys->fd, &st) || !S_ISREG(st.st_mode))
                return VLC_EGENERIC;
            const uint64_t stat =
                (i_query == STREAM_GET_SIZE) ? st.st_size : st.st_mtime;
            *va_arg( args, uint64_t * ) = stat;
            break;
        }

        case STREAM_GET_PTS_DELAY:
            pi_64 = va_arg( args, vlc_tick_t * );
            if (IsRemote (p_sys->fd, p_access->psz_filepath))
                *pi_64 = VLC_TICK_FROM_MS(
                        var_InheritInteger (p_access, "network-caching") );
            else
                *pi_64 = VLC_TICK_FROM_MS(
                        var_InheritInteger (p_access, "file-caching") );
            break;

        case STREAM_SET_PAUSE_STATE:
            /* Nothing to do */
            break;

        default:
            return VLC_EGENERIC;

    }
    return VLC_SUCCESS;
}

Messung
CHZG
839610093

¤ Dauer der Verarbeitung: 0.1 Sekunden  (vorverarbeitet am  2026-11-04) ¤

*© Formatika GbR, Deutschland






Wurzel

Suchen

PVS Prover

Isabelle Prover


Cephes Mathematical Library

Vienna Development Method

Haftungshinweis

Die Informationen auf dieser Webseite wurden nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit, noch Qualität der bereit gestellten Informationen zugesichert.

Bemerkung:

Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.






                                                                                                                                                                                                                                                                                                                                                                                                     


Neuigkeiten

     Aktuelles
     Motto des Tages

Open Source Software

     Quellcodebibliothek
     Eigene Quellcodes
     Fremde Quellcodes
     Suchen

Jenseits des Üblichen ....
    

Besucherstatistik

Besucherstatistik

Statistik
#Sources=1104852
#Domains=417161