[ff3a34b] | 1 | /*
|
---|
| 2 | * Copyright (c) 2007 Michal Konopa
|
---|
| 3 | * Copyright (c) 2007 Martin Jelen
|
---|
| 4 | * Copyright (c) 2007 Peter Majer
|
---|
| 5 | * All rights reserved.
|
---|
| 6 | *
|
---|
| 7 | * Redistribution and use in source and binary forms, with or without
|
---|
| 8 | * modification, are permitted provided that the following conditions
|
---|
| 9 | * are met:
|
---|
| 10 | *
|
---|
| 11 | * - Redistributions of source code must retain the above copyright
|
---|
| 12 | * notice, this list of conditions and the following disclaimer.
|
---|
| 13 | * - Redistributions in binary form must reproduce the above copyright
|
---|
| 14 | * notice, this list of conditions and the following disclaimer in the
|
---|
| 15 | * documentation and/or other materials provided with the distribution.
|
---|
| 16 | * - The name of the author may not be used to endorse or promote products
|
---|
| 17 | * derived from this software without specific prior written permission.
|
---|
| 18 | *
|
---|
| 19 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
|
---|
| 20 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
---|
| 21 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
|
---|
| 22 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
|
---|
| 23 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
|
---|
| 24 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
---|
| 25 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
---|
| 26 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
---|
| 27 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
|
---|
| 28 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
---|
| 29 | */
|
---|
| 30 |
|
---|
| 31 | /** @addtogroup libc
|
---|
| 32 | * @{
|
---|
| 33 | */
|
---|
| 34 |
|
---|
| 35 | /**
|
---|
| 36 | * @file file.c
|
---|
| 37 | * @brief The user library for working with the file system
|
---|
| 38 | */
|
---|
| 39 |
|
---|
| 40 | #include <stdio.h>
|
---|
| 41 | #include <stdlib.h>
|
---|
| 42 | #include <string.h>
|
---|
| 43 | #include <unistd.h>
|
---|
| 44 | #include <async.h>
|
---|
| 45 | #include <ipc/services.h>
|
---|
| 46 | #include <ipc/ipc.h>
|
---|
| 47 | #include <sys/mman.h>
|
---|
| 48 | #include <io/file.h>
|
---|
| 49 | #include <bool.h>
|
---|
| 50 | #include <err.h>
|
---|
| 51 | #include <align.h>
|
---|
| 52 | #include "../../../fs/dir.h"
|
---|
| 53 | #include "../../../share/message.h"
|
---|
| 54 | #include "../../../share/shared_proto.h"
|
---|
| 55 |
|
---|
| 56 | #define CONNECT_SLEEP_INTERVAL 10000
|
---|
| 57 | #define CONNECT_SLEEP_TIMEOUT 100000
|
---|
| 58 |
|
---|
| 59 | /**
|
---|
| 60 | *
|
---|
| 61 | */
|
---|
| 62 | static int fs_phone;
|
---|
| 63 |
|
---|
| 64 | static file_t *file_connect();
|
---|
| 65 | static int file_disconnect(file_t *file);
|
---|
| 66 |
|
---|
| 67 | /**
|
---|
| 68 | * Connect to the FS task and share memory with it for further data and
|
---|
| 69 | * extended memory transfers
|
---|
| 70 | */
|
---|
| 71 | file_t *file_connect() {
|
---|
| 72 | file_t *result;
|
---|
| 73 |
|
---|
| 74 | size_t size;
|
---|
| 75 | void *share = NULL;
|
---|
| 76 | int retval;
|
---|
| 77 |
|
---|
| 78 | size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
|
---|
| 79 | share = mmap(share, size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
|
---|
| 80 | if ((int) share < 0) {
|
---|
| 81 | f_err = F_MMAP_FAILURE;
|
---|
| 82 | return NULL;
|
---|
| 83 | }
|
---|
| 84 |
|
---|
| 85 | retval = async_req_2(fs_phone, FS_NEW_CONSUMER, task_get_id(), 0, NULL, NULL);
|
---|
| 86 | if (retval < 0) {
|
---|
| 87 | f_err = F_COMM_FAILURE;
|
---|
| 88 | return NULL;
|
---|
| 89 | }
|
---|
| 90 |
|
---|
| 91 | int flags = 0;
|
---|
| 92 | flags = AS_AREA_READ | AS_AREA_WRITE;
|
---|
| 93 | retval = async_req_3(fs_phone, IPC_M_AS_AREA_SEND, (uintptr_t)share, size, flags, NULL, NULL, NULL);
|
---|
| 94 | if (retval < 0) {
|
---|
| 95 | f_err = F_COMM_FAILURE;
|
---|
| 96 | return NULL;
|
---|
| 97 | }
|
---|
| 98 |
|
---|
| 99 | /* Allocating structure for extended message. */
|
---|
| 100 | message_params_t *params = malloc(sizeof(message_params_t));
|
---|
| 101 | memset((void*) params, 0, sizeof(message_params_t));
|
---|
| 102 |
|
---|
| 103 | result = malloc(sizeof(file_t));
|
---|
| 104 | result->share = share;
|
---|
| 105 | result->size = size;
|
---|
| 106 | result->params = params;
|
---|
| 107 |
|
---|
| 108 | f_err = F_OK;
|
---|
| 109 | return result;
|
---|
| 110 | }
|
---|
| 111 |
|
---|
| 112 | /**
|
---|
| 113 | * Disconnect from the FS task, unsharing memory and freeing the file data structure
|
---|
| 114 | */
|
---|
| 115 | int file_disconnect(file_t *file) {
|
---|
| 116 | int retval = send_request(fs_phone, FS_DROP_CONSUMER, file->params, file->share);
|
---|
| 117 | if (retval < 0)
|
---|
| 118 | return -1;
|
---|
| 119 |
|
---|
| 120 | /* Unmapping share area. */
|
---|
| 121 | retval = munmap(file->share, file->size);
|
---|
| 122 | if (retval < 0)
|
---|
| 123 | return -1;
|
---|
| 124 |
|
---|
| 125 | file->size = ALIGN_UP(BLOCK_SIZE * sizeof(char), PAGE_SIZE);
|
---|
| 126 | file->share = mmap(file->share, file->size, AS_AREA_READ | AS_AREA_WRITE, MAP_SHARED | MAP_ANONYMOUS, 0, 0);
|
---|
| 127 | if ((int) (file->share) < 0)
|
---|
| 128 | return -1;
|
---|
| 129 |
|
---|
| 130 | free(file);
|
---|
| 131 | f_err = F_OK;
|
---|
| 132 | return F_OK;
|
---|
| 133 | }
|
---|
| 134 |
|
---|
| 135 | /**
|
---|
| 136 | * List contents of the current directory
|
---|
| 137 | */
|
---|
| 138 | dir_item_t *ls(unsigned int *length) {
|
---|
| 139 | dir_item_t *result;
|
---|
| 140 | unsigned short entries_num;
|
---|
| 141 |
|
---|
| 142 | file_t *shared_file = file_connect();
|
---|
| 143 | if (shared_file == NULL)
|
---|
| 144 | return NULL;
|
---|
| 145 |
|
---|
| 146 | /* We want lookup our work directory. */
|
---|
| 147 | retval = send_request(fs_phone, FS_DSUM, shared_file->params, shared_file->share);
|
---|
| 148 | if (retval < 0) {
|
---|
| 149 | f_err = F_READ_ERROR;
|
---|
| 150 | return NULL;
|
---|
| 151 | }
|
---|
| 152 |
|
---|
| 153 | entries_num = retval;
|
---|
| 154 | *length = entries_num;
|
---|
| 155 |
|
---|
| 156 | result = malloc(entries_num * sizeof (dir_item_t));
|
---|
| 157 |
|
---|
| 158 | int entry;
|
---|
| 159 | for (entry = 0; entry < entries_num; entry++) {
|
---|
| 160 | shared_file->params->entry_number = entry;
|
---|
| 161 | retval = send_request(fs_phone, FS_READENTRY, shared_file->params, shared_file->share);
|
---|
| 162 | if (retval < 0) {
|
---|
| 163 | f_err = F_READ_ERROR;
|
---|
| 164 | return NULL;
|
---|
| 165 | }
|
---|
| 166 |
|
---|
| 167 | memcpy(&(result[entry].inode_num), shared_file->share, sizeof(unsigned short));
|
---|
| 168 | memcpy(result[entry].name, (void *)(shared_file->share+sizeof(unsigned short)), retval-sizeof(unsigned short));
|
---|
| 169 |
|
---|
| 170 | /* Do not show empty entries. */
|
---|
| 171 | if (!result[entry].inode_num)
|
---|
| 172 | continue;
|
---|
| 173 |
|
---|
| 174 | }
|
---|
| 175 | return result;
|
---|
| 176 | }
|
---|
| 177 |
|
---|
| 178 | /**
|
---|
| 179 | * Change the current working directory for the task
|
---|
| 180 | */
|
---|
| 181 | int chdir(char * new_dir)
|
---|
| 182 | {
|
---|
| 183 | file_t *shared_file = file_connect();
|
---|
| 184 |
|
---|
| 185 | if (shared_file == NULL) {
|
---|
| 186 | f_err = F_READ_ERROR;
|
---|
| 187 | return F_READ_ERROR;
|
---|
| 188 | }
|
---|
| 189 | memcpy(shared_file->params->fname, new_dir, 30);
|
---|
| 190 |
|
---|
| 191 | int retval = send_request(fs_phone, FS_CHDIR, shared_file->params, shared_file->share);
|
---|
| 192 | if (retval < 0) {
|
---|
| 193 | f_err = F_READ_ERROR;
|
---|
| 194 | return F_READ_ERROR;
|
---|
| 195 | }
|
---|
| 196 |
|
---|
| 197 | retval = file_disconnect(shared_file);
|
---|
| 198 | f_err = F_OK;
|
---|
| 199 | return F_OK;
|
---|
| 200 | }
|
---|
| 201 |
|
---|
| 202 | /**
|
---|
| 203 | * Open a file for reading and/or writing
|
---|
| 204 | */
|
---|
| 205 | file_t *fopen(char *name, int mode)
|
---|
| 206 | {
|
---|
| 207 | file_t *file = file_connect();
|
---|
| 208 |
|
---|
| 209 | /* We want to work with the specified file. */
|
---|
| 210 | memcpy(file->params->fname, name, 30);
|
---|
| 211 |
|
---|
| 212 | int retval = send_request(fs_phone, FS_OPEN, file->params, file->share);
|
---|
| 213 | if (retval < 0)
|
---|
| 214 | return NULL;
|
---|
| 215 |
|
---|
| 216 | file->handle = retval;
|
---|
| 217 |
|
---|
| 218 | return file;
|
---|
| 219 | }
|
---|
| 220 |
|
---|
| 221 | /**
|
---|
| 222 | * Read status information about a file
|
---|
| 223 | */
|
---|
| 224 | int fstat(file_t *file)
|
---|
| 225 | {
|
---|
| 226 | memcpy(file->params->fname, file->base_info.name, 30);
|
---|
| 227 | file->params->fd = file->handle;
|
---|
| 228 |
|
---|
| 229 | int retval = send_request(fs_phone, FS_FSTAT, file->params, file->share);
|
---|
| 230 | if (retval < 0)
|
---|
| 231 | return -1;
|
---|
| 232 |
|
---|
| 233 | memcpy((void *)(&file->stat), file->share, sizeof(stat_t));
|
---|
| 234 |
|
---|
| 235 | f_err = F_OK;
|
---|
| 236 | return F_OK;
|
---|
| 237 | }
|
---|
| 238 |
|
---|
| 239 | /**
|
---|
| 240 | * Read data from a file
|
---|
| 241 | */
|
---|
| 242 | int fread(file_t *file, void* buffer, unsigned int size)
|
---|
| 243 | {
|
---|
| 244 | file->params->nbytes = size;
|
---|
| 245 |
|
---|
| 246 | int retval = send_request(fs_phone, FS_READ, file->params, file->share);
|
---|
| 247 | if (retval < 0)
|
---|
| 248 | return -1;
|
---|
| 249 |
|
---|
| 250 | f_err = F_OK;
|
---|
| 251 | return F_OK;
|
---|
| 252 | }
|
---|
| 253 |
|
---|
| 254 | /**
|
---|
| 255 | * Seek to a position within a file
|
---|
| 256 | */
|
---|
| 257 | int fseek(file_t *file, int offset, int whence)
|
---|
| 258 | {
|
---|
| 259 | file->params->offset = 0;
|
---|
| 260 | file->params->whence = 0; /* from beginning of the file */
|
---|
| 261 |
|
---|
| 262 | int retval = send_request(fs_phone, FS_SEEK, file->params, file->share);
|
---|
| 263 | if (retval < 0)
|
---|
| 264 | return -1;
|
---|
| 265 |
|
---|
| 266 | f_err = F_OK;
|
---|
| 267 | return F_OK;
|
---|
| 268 | }
|
---|
| 269 |
|
---|
| 270 | /**
|
---|
| 271 | * Close a file
|
---|
| 272 | */
|
---|
| 273 | int fclose(file_t *file)
|
---|
| 274 | {
|
---|
| 275 | int retval = send_request(fs_phone, FS_CLOSE, file->params, file->share);
|
---|
| 276 | if (retval < 0)
|
---|
| 277 | return -1;
|
---|
| 278 |
|
---|
| 279 | if (file != NULL)
|
---|
| 280 | file_disconnect(file);
|
---|
| 281 |
|
---|
| 282 | f_err = F_OK;
|
---|
| 283 | return F_OK;
|
---|
| 284 | }
|
---|
| 285 |
|
---|
| 286 | /**
|
---|
| 287 | *@}
|
---|
| 288 | */
|
---|