Back to index

avfs  1.0.1
fdops.c
Go to the documentation of this file.
00001 /*
00002     AVFS: A Virtual File System Library
00003     Copyright (C) 2000  Miklos Szeredi <miklos@szeredi.hu>
00004 
00005     This program can be distributed under the terms of the GNU GPL.
00006     See the file COPYING.
00007 */
00008 
00009 #include "operutil.h"
00010 #include "internal.h"
00011 
00012 static vfile **file_table;
00013 static unsigned int file_table_size;
00014 static AV_LOCK_DECL(files_lock);
00015 
00016 static int find_unused()
00017 {
00018     int i;
00019     int newsize;
00020 
00021     for(i = 0; i < file_table_size; i++)
00022        if(file_table[i] == NULL)
00023            return i;
00024 
00025     newsize = file_table_size + 16;
00026     file_table = av_realloc(file_table, sizeof(*file_table) * newsize);
00027     for(i = file_table_size; i < newsize; i++)
00028        file_table[i] = NULL;
00029     
00030     i = file_table_size;
00031     file_table_size = newsize;
00032     
00033     return i;
00034 }
00035 
00036 
00037 static void put_file(vfile *vf)
00038 {
00039     AV_UNLOCK(vf->lock);
00040     av_unref_obj(vf);
00041 }
00042 
00043 static int get_file(int fd, vfile **resp)
00044 {
00045     vfile *vf = NULL;
00046 
00047     AV_LOCK(files_lock);
00048     if(fd >= 0 && fd < file_table_size) {
00049         vf = file_table[fd];
00050         if(vf != NULL)
00051             av_ref_obj(vf);
00052     }
00053     AV_UNLOCK(files_lock);
00054 
00055     if(vf == NULL)
00056         return -EBADF;
00057 
00058     AV_LOCK(vf->lock);
00059     if(vf->mnt == NULL) {
00060         put_file(vf);
00061         return -EBADF;
00062     }
00063     
00064     *resp = vf;
00065     
00066     return 0;
00067 }
00068 
00069 static void free_vfile(vfile *vf)
00070 {
00071     AV_FREELOCK(vf->lock);
00072 }
00073 
00074 int av_fd_open_entry(ventry *ve, int flags, avmode_t mode)
00075 {
00076     int res;
00077     int fd;
00078     vfile *vf;
00079 
00080     AV_NEW_OBJ(vf, free_vfile);
00081     AV_INITLOCK(vf->lock);
00082     res = av_file_open(vf, ve, flags, mode);
00083     if(res < 0) {
00084         av_unref_obj(vf);
00085         return res;
00086     }
00087 
00088     AV_LOCK(files_lock);
00089     fd = find_unused();
00090     file_table[fd] = vf;
00091     AV_UNLOCK(files_lock);
00092 
00093     return fd;
00094 }
00095 
00096 int av_fd_open(const char *path, int flags, avmode_t mode)
00097 {
00098     int res;
00099     ventry *ve;
00100     
00101     res = av_get_ventry(path, !(flags & AVO_NOFOLLOW), &ve);
00102     if(res < 0)
00103         return res;
00104 
00105     res = av_fd_open_entry(ve, flags, mode);
00106     av_free_ventry(ve);
00107 
00108     return res;
00109 }
00110 
00111 int av_fd_close(int fd)
00112 {
00113     int res;
00114     vfile *vf;
00115 
00116     res = get_file(fd, &vf);
00117     if(res == 0) {
00118         res = av_file_close(vf);
00119         put_file(vf);
00120 
00121         AV_LOCK(files_lock);
00122         file_table[fd] = NULL;
00123         AV_UNLOCK(files_lock);
00124 
00125         av_unref_obj(vf);
00126     }
00127 
00128     return res;
00129 }
00130 
00131 avssize_t av_fd_read(int fd, void *buf, avsize_t nbyte)
00132 {
00133     avssize_t res;
00134     vfile *vf;
00135 
00136     res = get_file(fd, &vf);
00137     if(res == 0) {
00138         res = av_file_read(vf, buf, nbyte);
00139         put_file(vf);
00140     }
00141 
00142     return res;
00143 }
00144 
00145 avssize_t av_fd_write(int fd, const char *buf, avsize_t nbyte)
00146 {
00147     avssize_t res;
00148     vfile *vf;
00149 
00150     res = get_file(fd, &vf);
00151     if(res == 0) {
00152         res = av_file_write(vf, buf, nbyte);
00153         put_file(vf);
00154     }
00155 
00156     return res;
00157 }
00158 
00159 static avoff_t dir_lseek(vfile *vf, avoff_t offset, int whence)
00160 {
00161     switch(whence) {
00162     case AVSEEK_SET:
00163         if(offset < 0)
00164             return -EINVAL;
00165 
00166         vf->ptr = offset;
00167         break;
00168         
00169     case AVSEEK_CUR:
00170         if(offset != 0)
00171             return -EINVAL;
00172         break;
00173         
00174     default:
00175         return -EINVAL;
00176     }
00177 
00178     return vf->ptr;
00179 }
00180 
00181 avoff_t av_fd_lseek(int fd, avoff_t offset, int whence)
00182 {
00183     avoff_t res;
00184     vfile *vf;
00185 
00186     res = get_file(fd, &vf);
00187     if(res == 0) {
00188         if((vf->flags & AVO_DIRECTORY) != 0)
00189             res = dir_lseek(vf, offset, whence);
00190         else
00191             res = av_file_lseek(vf, offset, whence);
00192        put_file(vf);
00193     }
00194 
00195     return res;
00196 }
00197 
00198 int av_fd_readdir(int fd, struct avdirent *buf, avoff_t *posp)
00199 {
00200     int res;
00201     vfile *vf;
00202 
00203     res = get_file(fd, &vf);
00204     if(res == 0) {
00205         struct avfs *avfs = vf->mnt->avfs;
00206 
00207        *posp = vf->ptr;
00208         AVFS_LOCK(avfs);
00209        res = avfs->readdir(vf, buf);
00210         AVFS_UNLOCK(avfs);
00211 
00212 
00213        put_file(vf);
00214     }
00215 
00216     return res;
00217 }
00218 
00219 int av_fd_getattr(int fd, struct avstat *buf, int attrmask)
00220 {
00221     int res;
00222     vfile *vf;
00223 
00224     res = get_file(fd, &vf);
00225     if(res == 0) {
00226         res = av_file_getattr(vf, buf, attrmask);
00227        put_file(vf);
00228     }
00229 
00230     return res;
00231 }
00232 
00233 int av_fd_setattr(int fd, struct avstat *buf, int attrmask)
00234 {
00235     int res;
00236     vfile *vf;
00237 
00238     res = get_file(fd, &vf);
00239     if(res == 0) {
00240         res = av_file_setattr(vf, buf, attrmask);
00241        put_file(vf);
00242     }
00243 
00244     return res;
00245 }
00246 
00247 int av_fd_truncate(int fd, avoff_t length)
00248 {
00249     int res;
00250     vfile *vf;
00251 
00252     res = get_file(fd, &vf);
00253     if(res == 0) {
00254         res = av_file_truncate(vf, length);
00255        put_file(vf);
00256     }
00257 
00258     return res;
00259 }
00260 
00261 void av_close_all_files()
00262 {
00263     int fd;
00264     vfile *vf;
00265     
00266     AV_LOCK(files_lock);
00267     for(fd = 0; fd < file_table_size; fd++) {
00268         vf = file_table[fd];
00269         if(vf != NULL) {
00270             av_log(AVLOG_WARNING, "File handle still in use: %i", fd);
00271             av_file_close(vf);
00272             av_unref_obj(vf);
00273         }
00274     }
00275     av_free(file_table);
00276     file_table = NULL;
00277     AV_UNLOCK(files_lock);
00278 }