~vojtech-horky/helenos/numa

« back to all changes in this revision

Viewing changes to uspace/srv/vfs/vfs_file.c

  • Committer: Martin Decky
  • Date: 2009-08-04 11:19:19 UTC
  • Revision ID: martin@uranus.dsrg.hide.ms.mff.cuni.cz-20090804111919-evyclddlr3v5lhmp
Initial import

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Copyright (c) 2007 Jakub Jermar
 
3
 * All rights reserved.
 
4
 *
 
5
 * Redistribution and use in source and binary forms, with or without
 
6
 * modification, are permitted provided that the following conditions
 
7
 * are met:
 
8
 *
 
9
 * - Redistributions of source code must retain the above copyright
 
10
 *   notice, this list of conditions and the following disclaimer.
 
11
 * - Redistributions in binary form must reproduce the above copyright
 
12
 *   notice, this list of conditions and the following disclaimer in the
 
13
 *   documentation and/or other materials provided with the distribution.
 
14
 * - The name of the author may not be used to endorse or promote products
 
15
 *   derived from this software without specific prior written permission.
 
16
 *
 
17
 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
 
18
 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 
19
 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
 
20
 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
 
21
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
 
22
 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 
23
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 
24
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 
25
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
 
26
 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
27
 */
 
28
 
 
29
/** @addtogroup fs
 
30
 * @{
 
31
 */ 
 
32
 
 
33
/**
 
34
 * @file        vfs_file.c
 
35
 * @brief       Various operations on files have their home in this file.
 
36
 */
 
37
 
 
38
#include <errno.h>
 
39
#include <stdlib.h>
 
40
#include <string.h>
 
41
#include <assert.h>
 
42
#include <bool.h>
 
43
#include <fibril.h>
 
44
#include <fibril_sync.h>
 
45
#include "vfs.h"
 
46
 
 
47
/**
 
48
 * This is a per-connection table of open files.
 
49
 * Our assumption is that each client opens only one connection and therefore
 
50
 * there is one table of open files per task. However, this may not be the case
 
51
 * and the client can open more connections to VFS. In that case, there will be
 
52
 * several tables and several file handle name spaces per task. Besides of this,
 
53
 * the functionality will stay unchanged. So unless the client knows what it is
 
54
 * doing, it should open one connection to VFS only.
 
55
 *
 
56
 * Allocation of the open files table is deferred until the client makes the
 
57
 * first VFS_OPEN operation.
 
58
 *
 
59
 * This resource being per-connection and, in the first place, per-fibril, we
 
60
 * don't need to protect it by a mutex.
 
61
 */
 
62
fibril_local vfs_file_t **files = NULL;
 
63
 
 
64
/** Initialize the table of open files. */
 
65
bool vfs_files_init(void)
 
66
{
 
67
        if (!files) {
 
68
                files = malloc(MAX_OPEN_FILES * sizeof(vfs_file_t *));
 
69
                if (!files)
 
70
                        return false;
 
71
                memset(files, 0, MAX_OPEN_FILES * sizeof(vfs_file_t *));
 
72
        }
 
73
        return true;
 
74
}
 
75
 
 
76
/** Allocate a file descriptor.
 
77
 *
 
78
 * @return              First available file descriptor or a negative error
 
79
 *                      code.
 
80
 */
 
81
int vfs_fd_alloc(void)
 
82
{
 
83
        if (!vfs_files_init())
 
84
                return ENOMEM;
 
85
        
 
86
        unsigned int i;
 
87
        for (i = 0; i < MAX_OPEN_FILES; i++) {
 
88
                if (!files[i]) {
 
89
                        files[i] = (vfs_file_t *) malloc(sizeof(vfs_file_t));
 
90
                        if (!files[i])
 
91
                                return ENOMEM;
 
92
                        
 
93
                        memset(files[i], 0, sizeof(vfs_file_t));
 
94
                        fibril_mutex_initialize(&files[i]->lock);
 
95
                        vfs_file_addref(files[i]);
 
96
                        return (int) i;
 
97
                }
 
98
        }
 
99
        
 
100
        return EMFILE;
 
101
}
 
102
 
 
103
/** Release file descriptor.
 
104
 *
 
105
 * @param fd            File descriptor being released.
 
106
 *
 
107
 * @return              EOK on success or EBADF if fd is an invalid file
 
108
 *                      descriptor.
 
109
 */
 
110
int vfs_fd_free(int fd)
 
111
{
 
112
        if (!vfs_files_init())
 
113
                return ENOMEM;
 
114
        
 
115
        if ((fd < 0) || (fd >= MAX_OPEN_FILES) || (files[fd] == NULL))
 
116
                return EBADF;
 
117
        
 
118
        vfs_file_delref(files[fd]);
 
119
        files[fd] = NULL;
 
120
        
 
121
        return EOK;
 
122
}
 
123
 
 
124
/** Increment reference count of VFS file structure.
 
125
 *
 
126
 * @param file          File structure that will have reference count
 
127
 *                      incremented.
 
128
 */
 
129
void vfs_file_addref(vfs_file_t *file)
 
130
{
 
131
        /*
 
132
         * File structures are per-connection, so no-one, except the current
 
133
         * fibril, should have a reference to them. This is the reason we don't
 
134
         * do any synchronization here.
 
135
         */
 
136
        file->refcnt++;
 
137
}
 
138
 
 
139
/** Decrement reference count of VFS file structure.
 
140
 *
 
141
 * @param file          File structure that will have reference count
 
142
 *                      decremented.
 
143
 */
 
144
void vfs_file_delref(vfs_file_t *file)
 
145
{
 
146
        if (file->refcnt-- == 1) {
 
147
                /*
 
148
                 * Lost the last reference to a file, need to drop our reference
 
149
                 * to the underlying VFS node.
 
150
                 */
 
151
                vfs_node_delref(file->node);
 
152
                free(file);
 
153
        }
 
154
}
 
155
 
 
156
/** Find VFS file structure for a given file descriptor.
 
157
 *
 
158
 * @param fd            File descriptor.
 
159
 *
 
160
 * @return              VFS file structure corresponding to fd.
 
161
 */
 
162
vfs_file_t *vfs_file_get(int fd)
 
163
{
 
164
        if (!vfs_files_init())
 
165
                return NULL;
 
166
        
 
167
        if ((fd >= 0) && (fd < MAX_OPEN_FILES))
 
168
                return files[fd];
 
169
        
 
170
        return NULL;
 
171
}
 
172
 
 
173
/**
 
174
 * @}
 
175
 */