Subversion Repositories HelenOS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2445 decky 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
 */