nkeynes@1152 | 1 | /*
|
nkeynes@1152 | 2 | * Copyright (c) 2007 Vreixo Formoso
|
nkeynes@1152 | 3 | * Copyright (c) 2009 Thomas Schmitt
|
nkeynes@1152 | 4 | *
|
nkeynes@1152 | 5 | * This file is part of the libisofs project; you can redistribute it and/or
|
nkeynes@1152 | 6 | * modify it under the terms of the GNU General Public License version 2
|
nkeynes@1152 | 7 | * or later as published by the Free Software Foundation.
|
nkeynes@1152 | 8 | * See COPYING file for details.
|
nkeynes@1152 | 9 | *
|
nkeynes@1152 | 10 | * Memory stream extracted for use in lxdream by Nathan Keynes 2010.
|
nkeynes@1152 | 11 | */
|
nkeynes@1152 | 12 |
|
nkeynes@1152 | 13 |
|
nkeynes@1152 | 14 | #include <stdlib.h>
|
nkeynes@1152 | 15 | #include <string.h>
|
nkeynes@1152 | 16 | #include <limits.h>
|
nkeynes@1152 | 17 | #include <stdio.h>
|
nkeynes@1179 | 18 | #include <stdint.h>
|
nkeynes@1179 | 19 | #include <libisofs.h>
|
nkeynes@1179 | 20 |
|
nkeynes@1152 | 21 |
|
nkeynes@1152 | 22 | #ifndef MIN
|
nkeynes@1152 | 23 | #define MIN(a,b) ((a)<=(b) ? (a) : (b))
|
nkeynes@1152 | 24 | #endif
|
nkeynes@1152 | 25 |
|
nkeynes@1152 | 26 | #define ISO_MEM_FS_ID 4
|
nkeynes@1152 | 27 |
|
nkeynes@1158 | 28 | static ino_t mem_serial_id = (ino_t)1;
|
nkeynes@1152 | 29 |
|
nkeynes@1152 | 30 | typedef struct
|
nkeynes@1152 | 31 | {
|
nkeynes@1152 | 32 | uint8_t *buf;
|
nkeynes@1152 | 33 | ssize_t offset; /* -1 if stream closed */
|
nkeynes@1152 | 34 | ino_t ino_id;
|
nkeynes@1152 | 35 | size_t size;
|
nkeynes@1152 | 36 | } MemStreamData;
|
nkeynes@1152 | 37 |
|
nkeynes@1152 | 38 | static
|
nkeynes@1152 | 39 | int mem_open(IsoStream *stream)
|
nkeynes@1152 | 40 | {
|
nkeynes@1152 | 41 | MemStreamData *data;
|
nkeynes@1152 | 42 | if (stream == NULL) {
|
nkeynes@1152 | 43 | return ISO_NULL_POINTER;
|
nkeynes@1152 | 44 | }
|
nkeynes@1152 | 45 | data = (MemStreamData*)stream->data;
|
nkeynes@1152 | 46 | if (data->offset != -1) {
|
nkeynes@1152 | 47 | return ISO_FILE_ALREADY_OPENED;
|
nkeynes@1152 | 48 | }
|
nkeynes@1152 | 49 | data->offset = 0;
|
nkeynes@1152 | 50 | return ISO_SUCCESS;
|
nkeynes@1152 | 51 | }
|
nkeynes@1152 | 52 |
|
nkeynes@1152 | 53 | static
|
nkeynes@1152 | 54 | int mem_close(IsoStream *stream)
|
nkeynes@1152 | 55 | {
|
nkeynes@1152 | 56 | MemStreamData *data;
|
nkeynes@1152 | 57 | if (stream == NULL) {
|
nkeynes@1152 | 58 | return ISO_NULL_POINTER;
|
nkeynes@1152 | 59 | }
|
nkeynes@1152 | 60 | data = (MemStreamData*)stream->data;
|
nkeynes@1152 | 61 | if (data->offset == -1) {
|
nkeynes@1152 | 62 | return ISO_FILE_NOT_OPENED;
|
nkeynes@1152 | 63 | }
|
nkeynes@1152 | 64 | data->offset = -1;
|
nkeynes@1152 | 65 | return ISO_SUCCESS;
|
nkeynes@1152 | 66 | }
|
nkeynes@1152 | 67 |
|
nkeynes@1152 | 68 | static
|
nkeynes@1152 | 69 | off_t mem_get_size(IsoStream *stream)
|
nkeynes@1152 | 70 | {
|
nkeynes@1152 | 71 | MemStreamData *data;
|
nkeynes@1152 | 72 | data = (MemStreamData*)stream->data;
|
nkeynes@1152 | 73 |
|
nkeynes@1152 | 74 | return (off_t)data->size;
|
nkeynes@1152 | 75 | }
|
nkeynes@1152 | 76 |
|
nkeynes@1152 | 77 | static
|
nkeynes@1152 | 78 | int mem_read(IsoStream *stream, void *buf, size_t count)
|
nkeynes@1152 | 79 | {
|
nkeynes@1152 | 80 | size_t len;
|
nkeynes@1152 | 81 | MemStreamData *data;
|
nkeynes@1152 | 82 | if (stream == NULL || buf == NULL) {
|
nkeynes@1152 | 83 | return ISO_NULL_POINTER;
|
nkeynes@1152 | 84 | }
|
nkeynes@1152 | 85 | if (count == 0) {
|
nkeynes@1152 | 86 | return ISO_WRONG_ARG_VALUE;
|
nkeynes@1152 | 87 | }
|
nkeynes@1152 | 88 | data = stream->data;
|
nkeynes@1152 | 89 |
|
nkeynes@1152 | 90 | if (data->offset == -1) {
|
nkeynes@1152 | 91 | return ISO_FILE_NOT_OPENED;
|
nkeynes@1152 | 92 | }
|
nkeynes@1152 | 93 |
|
nkeynes@1152 | 94 | if (data->offset >= data->size) {
|
nkeynes@1152 | 95 | return 0; /* EOF */
|
nkeynes@1152 | 96 | }
|
nkeynes@1152 | 97 |
|
nkeynes@1152 | 98 | len = MIN(count, data->size - data->offset);
|
nkeynes@1152 | 99 | memcpy(buf, data->buf + data->offset, len);
|
nkeynes@1152 | 100 | data->offset += len;
|
nkeynes@1152 | 101 | return len;
|
nkeynes@1152 | 102 | }
|
nkeynes@1152 | 103 |
|
nkeynes@1152 | 104 | static
|
nkeynes@1152 | 105 | int mem_is_repeatable(IsoStream *stream)
|
nkeynes@1152 | 106 | {
|
nkeynes@1152 | 107 | return 1;
|
nkeynes@1152 | 108 | }
|
nkeynes@1152 | 109 |
|
nkeynes@1152 | 110 | static
|
nkeynes@1152 | 111 | void mem_get_id(IsoStream *stream, unsigned int *fs_id, dev_t *dev_id,
|
nkeynes@1152 | 112 | ino_t *ino_id)
|
nkeynes@1152 | 113 | {
|
nkeynes@1152 | 114 | MemStreamData *data;
|
nkeynes@1152 | 115 | data = (MemStreamData*)stream->data;
|
nkeynes@1152 | 116 | *fs_id = ISO_MEM_FS_ID;
|
nkeynes@1152 | 117 | *dev_id = 0;
|
nkeynes@1152 | 118 | *ino_id = data->ino_id;
|
nkeynes@1152 | 119 | }
|
nkeynes@1152 | 120 |
|
nkeynes@1152 | 121 | static
|
nkeynes@1152 | 122 | void mem_free(IsoStream *stream)
|
nkeynes@1152 | 123 | {
|
nkeynes@1152 | 124 | MemStreamData *data;
|
nkeynes@1152 | 125 | data = (MemStreamData*)stream->data;
|
nkeynes@1152 | 126 | free(data->buf);
|
nkeynes@1152 | 127 | free(data);
|
nkeynes@1152 | 128 | }
|
nkeynes@1152 | 129 |
|
nkeynes@1227 | 130 | static IsoStreamIface mem_stream_class = {
|
nkeynes@1152 | 131 | 0,
|
nkeynes@1152 | 132 | "mem ",
|
nkeynes@1152 | 133 | mem_open,
|
nkeynes@1152 | 134 | mem_close,
|
nkeynes@1152 | 135 | mem_get_size,
|
nkeynes@1152 | 136 | mem_read,
|
nkeynes@1152 | 137 | mem_is_repeatable,
|
nkeynes@1152 | 138 | mem_get_id,
|
nkeynes@1152 | 139 | mem_free
|
nkeynes@1152 | 140 | };
|
nkeynes@1152 | 141 |
|
nkeynes@1152 | 142 | /**
|
nkeynes@1152 | 143 | * Create a stream for reading from a arbitrary memory buffer.
|
nkeynes@1152 | 144 | * When the Stream refcount reach 0, the buffer is free(3).
|
nkeynes@1152 | 145 | *
|
nkeynes@1152 | 146 | * @return
|
nkeynes@1152 | 147 | * 1 sucess, < 0 error
|
nkeynes@1152 | 148 | */
|
nkeynes@1152 | 149 | int iso_mem_stream_new(unsigned char *buf, size_t size, IsoStream **stream)
|
nkeynes@1152 | 150 | {
|
nkeynes@1152 | 151 | IsoStream *str;
|
nkeynes@1152 | 152 | MemStreamData *data;
|
nkeynes@1152 | 153 |
|
nkeynes@1152 | 154 | if (buf == NULL || stream == NULL) {
|
nkeynes@1152 | 155 | return ISO_NULL_POINTER;
|
nkeynes@1152 | 156 | }
|
nkeynes@1152 | 157 |
|
nkeynes@1152 | 158 | str = malloc(sizeof(IsoStream));
|
nkeynes@1152 | 159 | if (str == NULL) {
|
nkeynes@1152 | 160 | return ISO_OUT_OF_MEM;
|
nkeynes@1152 | 161 | }
|
nkeynes@1152 | 162 | data = malloc(sizeof(MemStreamData));
|
nkeynes@1152 | 163 | if (data == NULL) {
|
nkeynes@1152 | 164 | free(str);
|
nkeynes@1152 | 165 | return ISO_OUT_OF_MEM;
|
nkeynes@1152 | 166 | }
|
nkeynes@1152 | 167 |
|
nkeynes@1152 | 168 | /* fill data */
|
nkeynes@1152 | 169 | data->buf = buf;
|
nkeynes@1152 | 170 | data->size = size;
|
nkeynes@1152 | 171 | data->offset = -1;
|
nkeynes@1152 | 172 | data->ino_id = mem_serial_id++;
|
nkeynes@1152 | 173 |
|
nkeynes@1152 | 174 | str->refcount = 1;
|
nkeynes@1152 | 175 | str->data = data;
|
nkeynes@1152 | 176 | str->class = &mem_stream_class;
|
nkeynes@1152 | 177 |
|
nkeynes@1152 | 178 | *stream = str;
|
nkeynes@1152 | 179 | return ISO_SUCCESS;
|
nkeynes@1152 | 180 | }
|