file_posix.c 4.65 KB
Newer Older
1 2
/*
 * This file is part of libbluray
3
 * Copyright (C) 2009-2010  Obliter0n
4 5
 * Copyright (C) 2009-2010  John Stebbins
 *
gates's avatar
gates committed
6 7 8 9
 * This library 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.
10
 *
gates's avatar
gates committed
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
gates's avatar
gates committed
13 14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
15
 *
gates's avatar
gates committed
16 17 18
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library. If not, see
 * <http://www.gnu.org/licenses/>.
19 20
 */

21 22 23
#if HAVE_CONFIG_H
#include "config.h"
#endif
cRTrn13's avatar
cRTrn13 committed
24

25 26 27 28
#include "file.h"
#include "util/macro.h"
#include "util/logging.h"

29
#include <errno.h>
30
#include <inttypes.h>
Petri Hintukainen's avatar
Petri Hintukainen committed
31 32 33 34 35 36 37 38
#include <stdio.h> // remove()
#include <stdlib.h>
#include <string.h>

#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
cRTrn13's avatar
cRTrn13 committed
39

40
static void file_close_linux(BD_FILE_H *file)
cRTrn13's avatar
cRTrn13 committed
41
{
cRTrn13's avatar
cRTrn13 committed
42
    if (file) {
Petri Hintukainen's avatar
Petri Hintukainen committed
43
        close((int)(intptr_t)file->internal);
44

45
        BD_DEBUG(DBG_FILE, "Closed LINUX file (%p)\n", (void*)file);
46

cRTrn13's avatar
cRTrn13 committed
47 48
        X_FREE(file);
    }
cRTrn13's avatar
cRTrn13 committed
49 50
}

51
static int64_t file_seek_linux(BD_FILE_H *file, int64_t offset, int32_t origin)
cRTrn13's avatar
cRTrn13 committed
52
{
Petri Hintukainen's avatar
Petri Hintukainen committed
53 54 55 56 57 58
    off_t result = lseek((int)(intptr_t)file->internal, offset, origin);
    if (result == (off_t)-1) {
        BD_DEBUG(DBG_FILE, "lseek() failed (%p)\n", (void*)file);
        return -1;
    }
    return (int64_t)result;
cRTrn13's avatar
cRTrn13 committed
59 60
}

61
static int64_t file_tell_linux(BD_FILE_H *file)
cRTrn13's avatar
cRTrn13 committed
62
{
Petri Hintukainen's avatar
Petri Hintukainen committed
63
    return file_seek_linux(file, 0, SEEK_CUR);
cRTrn13's avatar
cRTrn13 committed
64
}
cRTrn13's avatar
cRTrn13 committed
65

66
#if 0
67
static int file_eof_linux(BD_FILE_H *file)
68 69 70
{
    return feof((FILE *)file->internal);
}
71
#endif
72

73
static int64_t file_read_linux(BD_FILE_H *file, uint8_t *buf, int64_t size)
cRTrn13's avatar
cRTrn13 committed
74
{
Petri Hintukainen's avatar
Petri Hintukainen committed
75 76 77 78 79
    ssize_t got, result;

    if (size <= 0 || size >= BD_MAX_SSIZE) {
        BD_DEBUG(DBG_FILE | DBG_CRIT, "Ignoring invalid read of size %"PRId64" (%p)\n", size, (void*)file);
        return 0;
80 81
    }

Petri Hintukainen's avatar
Petri Hintukainen committed
82 83 84
    for (got = 0; got < (ssize_t)size; got += result) {
        result = read((int)(intptr_t)file->internal, buf + got, size - got);
        if (result < 0) {
85 86 87 88 89
            if (errno != EINTR) {
                BD_DEBUG(DBG_FILE, "read() failed (%p)\n", (void*)file);
                break;
            }
            result = 0;
Petri Hintukainen's avatar
Petri Hintukainen committed
90 91 92 93 94 95
        } else if (result == 0) {
            // hit EOF.
            break;
        }
    }
    return (int64_t)got;
cRTrn13's avatar
cRTrn13 committed
96 97
}

98
static int64_t file_write_linux(BD_FILE_H *file, const uint8_t *buf, int64_t size)
cRTrn13's avatar
cRTrn13 committed
99
{
Petri Hintukainen's avatar
Petri Hintukainen committed
100 101 102 103 104
    ssize_t written, result;

    if (size <= 0 || size >= BD_MAX_SSIZE) {
        BD_DEBUG(DBG_FILE | DBG_CRIT, "Ignoring invalid write of size %"PRId64" (%p)\n", size, (void*)file);
        return 0;
105 106
    }

Petri Hintukainen's avatar
Petri Hintukainen committed
107 108 109
    for (written = 0; written < (ssize_t)size; written += result) {
        result = write((int)(intptr_t)file->internal, buf + written, size - written);
        if (result < 0) {
110 111 112 113 114
            if (errno != EINTR) {
                BD_DEBUG(DBG_FILE, "write() failed (%p)\n", (void*)file);
                break;
            }
            result = 0;
Petri Hintukainen's avatar
Petri Hintukainen committed
115 116 117
        }
    }
    return (int64_t)written;
cRTrn13's avatar
cRTrn13 committed
118
}
cRTrn13's avatar
cRTrn13 committed
119

Petri Hintukainen's avatar
Petri Hintukainen committed
120
static BD_FILE_H *file_open_linux(const char* filename, const char *cmode)
cRTrn13's avatar
cRTrn13 committed
121
{
Petri Hintukainen's avatar
Petri Hintukainen committed
122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151
    BD_FILE_H *file;
    int fd    = -1;
    int flags = 0;
    int mode  = 0;

    if (strchr(cmode, 'w')) {
        flags = O_WRONLY | O_CREAT | O_TRUNC;
        mode  = S_IRUSR | S_IWUSR;
    } else {
        flags = O_RDONLY;
    }

#ifdef O_CLOEXEC
    flags |= O_CLOEXEC;
#endif
#ifdef O_BINARY
    flags |= O_BINARY;
#endif

    if ((fd = open(filename, flags, mode)) < 0) {
        BD_DEBUG(DBG_FILE, "Error opening file %s\n", filename);
        return NULL;
    }

    file = calloc(1, sizeof(BD_FILE_H));
    if (!file) {
        close(fd);
        BD_DEBUG(DBG_FILE, "Error opening file %s (out of memory)\n", filename);
        return NULL;
    }
cRTrn13's avatar
cRTrn13 committed
152 153

    file->close = file_close_linux;
cRTrn13's avatar
cRTrn13 committed
154
    file->seek = file_seek_linux;
cRTrn13's avatar
cRTrn13 committed
155
    file->read = file_read_linux;
156
    file->write = file_write_linux;
cRTrn13's avatar
cRTrn13 committed
157
    file->tell = file_tell_linux;
158
    //file->eof = file_eof_linux;
cRTrn13's avatar
cRTrn13 committed
159

Petri Hintukainen's avatar
Petri Hintukainen committed
160
    file->internal = (void*)(intptr_t)fd;
161

162
    BD_DEBUG(DBG_FILE, "Opened LINUX file %s (%p)\n", filename, (void*)file);
Petri Hintukainen's avatar
Petri Hintukainen committed
163
    return file;
cRTrn13's avatar
cRTrn13 committed
164
}
165

166
BD_FILE_H* (*file_open)(const char* filename, const char *mode) = file_open_linux;
167 168 169 170 171

BD_FILE_OPEN file_open_default(void)
{
    return file_open_linux;
}
172 173 174 175 176

int file_unlink(const char *file)
{
    return remove(file);
}
177 178 179 180 181 182 183 184 185 186 187 188 189 190

#include <sys/stat.h>
#include <sys/types.h>

int file_path_exists(const char *path)
{
    struct stat s;
    return stat(path, &s);
}

int file_mkdir(const char *dir)
{
    return mkdir(dir, S_IRWXU);
}