file_posix.c 4.32 KB
Newer Older
1
/*
Ano Nymous's avatar
Ano Nymous committed
2
 * This file is part of libaacs
3
 * Copyright (C) 2009-2010  Obliter0n
4
 *
gates's avatar
gates committed
5
6
7
8
 * 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.
9
 *
gates's avatar
gates committed
10
 * This library is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
gates's avatar
gates committed
12
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
14
 *
gates's avatar
gates committed
15
16
17
 * 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/>.
18
19
 */

20
21
22
23
#if HAVE_CONFIG_H
#include "config.h"
#endif

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

28
#include <errno.h>
npzacs's avatar
npzacs committed
29
#include <inttypes.h>
npzacs's avatar
npzacs committed
30
#include <stdio.h> // remove()
Accident's avatar
   
Accident committed
31
#include <stdlib.h>
32
#include <string.h>
cRTrn13's avatar
cRTrn13 committed
33

34
35
#include <fcntl.h>
#include <unistd.h>
36
37
38
#include <sys/stat.h>
#include <sys/types.h>

npzacs's avatar
npzacs committed
39
static void _file_close(AACS_FILE_H *file)
cRTrn13's avatar
cRTrn13 committed
40
{
cRTrn13's avatar
cRTrn13 committed
41
    if (file) {
42
        close((int)(intptr_t)file->internal);
43

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

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

npzacs's avatar
npzacs committed
50
static int64_t _file_seek(AACS_FILE_H *file, int64_t offset, int32_t origin)
cRTrn13's avatar
cRTrn13 committed
51
{
52
53
54
55
56
57
    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
58
59
}

npzacs's avatar
npzacs committed
60
static int64_t _file_tell(AACS_FILE_H *file)
cRTrn13's avatar
cRTrn13 committed
61
{
62
    return _file_seek(file, 0, SEEK_CUR);
cRTrn13's avatar
cRTrn13 committed
63
}
cRTrn13's avatar
cRTrn13 committed
64

npzacs's avatar
npzacs committed
65
static int64_t _file_read(AACS_FILE_H *file, uint8_t *buf, int64_t size)
cRTrn13's avatar
cRTrn13 committed
66
{
67
68
    ssize_t got, result;

npzacs's avatar
npzacs committed
69
70
71
72
73
    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;
    }

74
75
76
77
78
79
80
81
82
83
84
85
86
87
    for (got = 0; got < (ssize_t)size; got += result) {
        result = read((int)(intptr_t)file->internal, buf + got, size - got);
        if (result < 0) {
            if (errno != EINTR) {
                BD_DEBUG(DBG_FILE, "read() failed (%p)\n", (void*)file);
                break;
            }
            result = 0;
        } else if (result == 0) {
            // hit EOF.
            break;
        }
    }
    return (int64_t)got;
cRTrn13's avatar
cRTrn13 committed
88
89
}

npzacs's avatar
npzacs committed
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
static int64_t _file_write(AACS_FILE_H *file, const uint8_t *buf, int64_t size)
{
    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;
    }

    for (written = 0; written < (ssize_t)size; written += result) {
        result = write((int)(intptr_t)file->internal, buf + written, size - written);
        if (result < 0) {
            if (errno != EINTR) {
                BD_DEBUG(DBG_FILE, "write() failed (%p)\n", (void*)file);
                break;
            }
            result = 0;
        }
    }
    return (int64_t)written;
}

112
static AACS_FILE_H *_file_open(const char* filename, const char *cmode)
cRTrn13's avatar
cRTrn13 committed
113
{
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
    AACS_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(AACS_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
144

npzacs's avatar
npzacs committed
145
146
147
    file->close = _file_close;
    file->seek  = _file_seek;
    file->read  = _file_read;
npzacs's avatar
npzacs committed
148
    file->write = _file_write;
npzacs's avatar
npzacs committed
149
    file->tell  = _file_tell;
cRTrn13's avatar
cRTrn13 committed
150

151
    file->internal = (void*)(intptr_t)fd;
152

153
    BD_DEBUG(DBG_FILE, "Opened POSIX file %s (%p)\n", filename, (void*)file);
154

155
    return file;
cRTrn13's avatar
cRTrn13 committed
156
}
157

npzacs's avatar
npzacs committed
158
AACS_FILE_H* (*file_open)(const char* filename, const char *mode) = _file_open;
159

npzacs's avatar
npzacs committed
160
161
162
163
164
int file_unlink(const char *file)
{
    return remove(file);
}

npzacs's avatar
npzacs committed
165
166
167
168
169
170
int file_path_exists(const char *path)
{
    struct stat s;
    return stat(path, &s);
}

171
172
173
174
int file_mkdir(const char *dir)
{
    return mkdir(dir, S_IRWXU);
}