Blame contrib/libudfread/src/default_blockinput.c

Packit 5e46da
/*
Packit 5e46da
 * This file is part of libudfread
Packit 5e46da
 * Copyright (C) 2014-2017 VLC authors and VideoLAN
Packit 5e46da
 *
Packit 5e46da
 * Authors: Petri Hintukainen <phintuka@users.sourceforge.net>
Packit 5e46da
 *
Packit 5e46da
 * This library is free software; you can redistribute it and/or
Packit 5e46da
 * modify it under the terms of the GNU Lesser General Public
Packit 5e46da
 * License as published by the Free Software Foundation; either
Packit 5e46da
 * version 2.1 of the License, or (at your option) any later version.
Packit 5e46da
 *
Packit 5e46da
 * This library is distributed in the hope that it will be useful,
Packit 5e46da
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 5e46da
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 5e46da
 * Lesser General Public License for more details.
Packit 5e46da
 *
Packit 5e46da
 * You should have received a copy of the GNU Lesser General Public
Packit 5e46da
 * License along with this library. If not, see
Packit 5e46da
 * <http://www.gnu.org/licenses/>.
Packit 5e46da
 */
Packit 5e46da
Packit 5e46da
#if HAVE_CONFIG_H
Packit 5e46da
#include "config.h"
Packit 5e46da
#endif
Packit 5e46da
Packit 5e46da
#include "default_blockinput.h"
Packit 5e46da
#include "blockinput.h"
Packit 5e46da
Packit 5e46da
#include <errno.h>
Packit 5e46da
#include <stdlib.h>
Packit 5e46da
#ifdef HAVE_UNISTD_H
Packit 5e46da
#include <unistd.h>
Packit 5e46da
#endif
Packit 5e46da
#ifdef HAVE_FCNTL_H
Packit 5e46da
#include <fcntl.h>
Packit 5e46da
#endif
Packit 5e46da
Packit 5e46da
#ifdef _WIN32
Packit 5e46da
#include <windows.h>
Packit 5e46da
#ifndef HAVE_UNISTD_H
Packit 5e46da
#include <stdio.h>
Packit 5e46da
#endif
Packit 5e46da
#include <io.h>
Packit 5e46da
# undef  lseek
Packit 5e46da
# define lseek _lseeki64
Packit 5e46da
# undef  off_t
Packit 5e46da
# define off_t int64_t
Packit 5e46da
#endif
Packit 5e46da
Packit 5e46da
#ifdef __ANDROID__
Packit 5e46da
# undef  lseek
Packit 5e46da
# define lseek lseek64
Packit 5e46da
# undef  off_t
Packit 5e46da
# define off_t off64_t
Packit 5e46da
#endif
Packit 5e46da
Packit 5e46da
#ifdef _WIN32
Packit 5e46da
static ssize_t pread(int fd, void *buf, size_t count, off_t offset)
Packit 5e46da
{
Packit 5e46da
    OVERLAPPED ov;
Packit 5e46da
    DWORD      got;
Packit 5e46da
    HANDLE     handle;
Packit 5e46da
Packit 5e46da
    handle = (HANDLE)(intptr_t)_get_osfhandle(fd);
Packit 5e46da
    if (handle == INVALID_HANDLE_VALUE) {
Packit 5e46da
        return -1;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    memset(&ov, 0, sizeof(ov));
Packit 5e46da
    ov.Offset     = (DWORD)offset;
Packit 5e46da
    ov.OffsetHigh = (offset >> 32);
Packit 5e46da
    if (!ReadFile(handle, buf, count, &got, &ov)) {
Packit 5e46da
        return -1;
Packit 5e46da
    }
Packit 5e46da
    return got;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
#elif defined (NEED_PREAD_IMPL)
Packit 5e46da
Packit 5e46da
#include <pthread.h>
Packit 5e46da
static ssize_t pread_impl(int fd, void *buf, size_t count, off_t offset)
Packit 5e46da
{
Packit 5e46da
    static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER;
Packit 5e46da
    ssize_t result;
Packit 5e46da
Packit 5e46da
    pthread_mutex_lock(&lock);
Packit 5e46da
Packit 5e46da
    if (lseek(fd, offset, SEEK_SET) != offset) {
Packit 5e46da
        result = -1;
Packit 5e46da
    } else {
Packit 5e46da
        result = read(fd, buf, count);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    pthread_mutex_unlock(&lock);
Packit 5e46da
    return result;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
#define pread(a,b,c,d) pread_impl(a,b,c,d)
Packit 5e46da
Packit 5e46da
#endif /* _WIN32 || NEED_PREAD_IMPL */
Packit 5e46da
Packit 5e46da
Packit 5e46da
typedef struct default_block_input {
Packit 5e46da
    udfread_block_input input;
Packit 5e46da
    int                 fd;
Packit 5e46da
} default_block_input;
Packit 5e46da
Packit 5e46da
Packit 5e46da
static int _def_close(udfread_block_input *p_gen)
Packit 5e46da
{
Packit 5e46da
    default_block_input *p = (default_block_input *)p_gen;
Packit 5e46da
    int result = -1;
Packit 5e46da
Packit 5e46da
    if (p) {
Packit 5e46da
        if (p->fd >= 0) {
Packit 5e46da
            result = close(p->fd);
Packit 5e46da
        }
Packit 5e46da
        free(p);
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    return result;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
static uint32_t _def_size(udfread_block_input *p_gen)
Packit 5e46da
{
Packit 5e46da
    default_block_input *p = (default_block_input *)p_gen;
Packit 5e46da
    off_t pos;
Packit 5e46da
Packit 5e46da
    pos = lseek(p->fd, 0, SEEK_END);
Packit 5e46da
    if (pos < 0) {
Packit 5e46da
        return 0;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    return (uint32_t)(pos / UDF_BLOCK_SIZE);
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
static int _def_read(udfread_block_input *p_gen, uint32_t lba, void *buf, uint32_t nblocks, int flags)
Packit 5e46da
{
Packit 5e46da
    default_block_input *p = (default_block_input *)p_gen;
Packit 5e46da
    size_t bytes, got;
Packit 5e46da
    off_t  pos;
Packit 5e46da
Packit 5e46da
    (void)flags;
Packit 5e46da
Packit 5e46da
    bytes = (size_t)nblocks * UDF_BLOCK_SIZE;
Packit 5e46da
    got   = 0;
Packit 5e46da
    pos   = (off_t)lba * UDF_BLOCK_SIZE;
Packit 5e46da
Packit 5e46da
    while (got < bytes) {
Packit 5e46da
        ssize_t ret = pread(p->fd, ((char*)buf) + got, bytes - got, pos + (off_t)got);
Packit 5e46da
Packit 5e46da
        if (ret <= 0) {
Packit 5e46da
            if (ret < 0 && errno == EINTR) {
Packit 5e46da
                continue;
Packit 5e46da
            }
Packit 5e46da
            if (got < UDF_BLOCK_SIZE) {
Packit 5e46da
                return ret;
Packit 5e46da
            }
Packit 5e46da
            break;
Packit 5e46da
        }
Packit 5e46da
        got += (size_t)ret;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    return got / UDF_BLOCK_SIZE;
Packit 5e46da
}
Packit 5e46da
Packit 5e46da
udfread_block_input *block_input_new(const char *path)
Packit 5e46da
{
Packit 5e46da
    default_block_input *p = (default_block_input*)calloc(1, sizeof(default_block_input));
Packit 5e46da
    if (!p) {
Packit 5e46da
        return NULL;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
#ifdef _WIN32
Packit 5e46da
    p->fd = open(path, O_RDONLY | O_BINARY);
Packit 5e46da
#else
Packit 5e46da
    p->fd = open(path, O_RDONLY);
Packit 5e46da
#endif
Packit 5e46da
    if(p->fd < 0) {
Packit 5e46da
        free(p);
Packit 5e46da
        return NULL;
Packit 5e46da
    }
Packit 5e46da
Packit 5e46da
    p->input.close = _def_close;
Packit 5e46da
    p->input.read  = _def_read;
Packit 5e46da
    p->input.size  = _def_size;
Packit 5e46da
Packit 5e46da
    return &p->input;
Packit 5e46da
}