|
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 |
}
|