# file.c

Go to the documentation of this file.

    00001 /*****************************************************************************************
    00002  Copyright (c) 2002 The UbixOS Project
    00003  All rights reserved.
    00004
    00005 Redistribution and use in source and binary forms, with or without modification, are
    00006 permitted provided that the following conditions are met:
    00007
    00008 Redistributions of source code must retain the above copyright notice, this list of
    00009 conditions, the following disclaimer and the list of authors.  Redistributions in binary
    00010 form must reproduce the above copyright notice, this list of conditions, the following
    00011 disclaimer and the list of authors in the documentation and/or other materials provided
    00012 with the distribution. Neither the name of the UbixOS Project nor the names of its
    00013 contributors may be used to endorse or promote products derived from this software
    00014 without specific prior written permission.
    00015
    00016 THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY
    00017 EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
    00018 MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
    00019 THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    00020 SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
    00021 OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
    00022 HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
    00023 TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
    00024 SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    00025
    00026  $Id: file_8c-source.html 88 2016-01-12 00:11:29Z reddawg $
    00027
    00028 *****************************************************************************************/
    00029
    00030 #include <vfs/vfs.h>
    00031 #include <vfs/file.h>
    00032 #include <ubixos/sched.h>
    00033 #include <ubixos/vitals.h>
    00034 #include <ubixos/kpanic.h>
    00035 #include <ubixos/spinlock.h>
    00036 #include <lib/kmalloc.h>
    00037 #include <lib/string.h>
    00038 #include <vmm/paging.h>
    00039 #include <lib/kprintf.h>
    00040 #include <assert.h>
    00041
    00042 static spinLock_t fdTable_lock = SPIN_LOCK_INITIALIZER;
    00043
    00044
    00045 fileDescriptor *fdTable = 0x0;
    00046
    00047 /* USER */
    00048
    00049 void sysFwrite(char *ptr,int size,userFileDescriptor *userFd) {
    00050   if (userFd == 0x0) {
    00051       tty_print(ptr,_current->term);
    00052     }
    00053   else {
    00054     fwrite(ptr,size,1,userFd->fd);
    00055     }
    00056   return;
    00057   }
    00058
    00059 void sysFgetc(int *ptr,userFileDescriptor *userFd) {
    00060   fileDescriptor *tmpFd = 0x0;
    00061   tmpFd = userFd->fd;
    00062   if (userFd->fd == 0x0) {
    00063     while (1) {
    00064       if (_current->term == tty_foreground) {
    00065         if ((*ptr = getch()) != 0x0)
    00066           return;
    00067         sched_yield();
    00068         }
    00069       else {
    00070         sched_yield();
    00071         }
    00072  /*
    00073        else {
    00074          kprintf("Waking Task: %i\n",tty_foreground->owner);
    00075          sched_setStatus(tty_foreground->owner,READY);
    00076          kprintf("Sleeping Task: %i\n",_current->id);
    00077          sched_setStatus(_current->id,WAIT);
    00078          sched_yield();
    00079          }
    00080 */
    00081       }
    00082     }
    00083   else {
    00084     ptr[0] = (int) fgetc(tmpFd);
    00085     }
    00086   }
    00087
    00088 void sysRmDir() {
    00089   return;
    00090   }
    00091
    00092 void sysFseek(userFileDescriptor *userFd,long offset,int whence) {
    00093   // TODO : coredump?
    00094   if (userFd == NULL)
    00095         return;
    00096   if (userFd->fd == NULL)
    00097         return;
    00098
    00099   userFd->fd->offset = offset+whence;
    00100   }
    00101
    00102 void sysChDir(const char *path) {
    00103   if (strstr(path,":") == 0x0) {
    00104     sprintf(_current->oInfo.cwd,"%s%s",_current->oInfo.cwd,path);
    00105     }
    00106   else {
    00107     sprintf(_current->oInfo.cwd,path);
    00108     }
    00109   }
    00110
    00111 void sysUnlink(const char *path,int *retVal) {
    00112   *retVal = unlink(path);
    00113   }
    00114
    00115 /************************************************************************
    00116
    00117 Function: void sysFopen();
    00118 Description: Opens A File Descriptor For A User Task
    00119 Notes:
    00120
    00121 ************************************************************************/
    00122 void sysFopen(const char *file,char *flags,userFileDescriptor *userFd) {
    00123   if (userFd == NULL)
    00124     kprintf("Error: userFd == NULL, File: %s, Line: %i\n",__FILE__,__LINE__);
    00125   userFd->fd = fopen(file,flags);
    00126   if (userFd->fd != 0x0) {
    00127     userFd->fdSize = userFd->fd->size;
    00128     }
    00129   /* Return */
    00130   return;
    00131   }
    00132
    00133 /************************************************************************
    00134
    00135 Function: void sysFread();
    00136 Description: Reads SIZE Bytes From The userFd Into DATA
    00137 Notes:
    00138
    00139 ************************************************************************/
    00140 void sysFread(void *data,long size,userFileDescriptor *userFd) {
    00141   /* TODO : coredump? */
    00142   if (userFd == NULL)
    00143         return;
    00144   if (userFd->fd == NULL)
    00145         return;
    00146   fread(data,size,1,userFd->fd);
    00147     return;
    00148   }
    00149
    00150 /************************************************************************
    00151
    00152 Function: void sysFclse();
    00153 Description: Closes A File Descriptor For A User Task
    00154 Notes:
    00155
    00156 ************************************************************************/
    00157 void sysFclose(userFileDescriptor *userFd,int *status) {
    00158   if (userFd == NULL )
    00159   {
    00160         *status = -1;
    00161         return;
    00162   }
    00163   if (userFd->fd == NULL)
    00164   {
    00165         *status = -1;
    00166         return;
    00167   }
    00168   *status = fclose(userFd->fd);
    00169   /* Return */
    00170   return;
    00171   }
    00172
    00173
    00174
    00175 /* KERNEL */
    00176
    00177
    00178 size_t fread(void *ptr,size_t size,size_t nmemb,fileDescriptor *fd) {
    00179   size_t i = 0x0;
    00180
    00181   if (fd == 0x0)
    00182     return(0x0);
    00183
    00184    if (nmemb == 0x0)
    00185      nmemb = 1; //Temp Fix
    00186
    00187    assert(fd);
    00188    assert(fd->mp);
    00189    assert(fd->mp->fs);
    00190
    00191    i = fd->mp->fs->vfsRead(fd,ptr,fd->offset,size * nmemb);
    00192
    00193    fd->offset += size * nmemb;
    00194
    00195    //kprintf("fread: %i:%i",i,size *nmemb);
    00196
    00197    return(i);
    00198   }
    00199
    00200 size_t fwrite(void *ptr,int size,int nmemb,fileDescriptor *fd) {
    00201   if (fd != 0x0) {
    00202     fd->mp->fs->vfsWrite(fd,ptr,fd->offset,size * nmemb);
    00203     fd->offset += size * nmemb;
    00204     }
    00205   return(0x0);
    00206   }
    00207
    00208 int fseek(fileDescriptor *tmpFd,long offset,int whence) {
    00209   tmpFd->offset = offset+whence;
    00210   return(tmpFd->offset);
    00211   }
    00212
    00213 /************************************************************************
    00214
    00215 Function: int feof(fileDescriptor *fd)
    00216 Description: Check A File Descriptor For EOF And Return Result
    00217 Notes:
    00218
    00219 ************************************************************************/
    00220 int feof(fileDescriptor *fd) {
    00221   if (fd->status == fdEof) {
    00222     return(-1);
    00223     }
    00224   return(0);
    00225   }
    00226
    00227 /************************************************************************
    00228
    00229 Function: int fputc(int ch,fileDescriptor *fd)
    00230 Description: This Will Write Character To FD
    00231 Notes:
    00232
    00233 ************************************************************************/
    00234 int fputc(int ch,fileDescriptor *fd) {
    00235   if (fd != 0x0) {
    00236     ch = fd->mp->fs->vfsWrite(fd,(char *)ch,fd->offset,1);
    00237     fd->offset++;
    00238     return(ch);
    00239     }
    00240   /* Return NULL If FD Is Not Found */
    00241   return(0x0);
    00242   }
    00243
    00244 /************************************************************************
    00245
    00246 Function: int fgetc(fileDescriptor *fd)
    00247 Description: This Will Return The Next Character In A FD Stream
    00248 Notes:
    00249
    00250 ************************************************************************/
    00251 int fgetc(fileDescriptor *fd) {
    00252   int ch = 0x0;
    00253   /* If Found Return Next Char */
    00254   if (fd != 0x0) {
    00255     fd->mp->fs->vfsRead(fd,(char *)&ch,fd->offset,1);
    00256     fd->offset++;
    00257     return(ch);
    00258     }
    00259
    00260   /* Return NULL If FD Is Not Found */
    00261   return(0x0);
    00262   }
    00263
    00264 /************************************************************************
    00265
    00266 Function: fileDescriptor *fopen(const char *file,cont char *flags)
    00267 Description: This Will Open A File And Return A File Descriptor
    00268 Notes:
    00269
    00270 08/05/02 - Just Started A Rewrite Of This Function Should Work Out Well
    00271
    00272 ************************************************************************/
    00273
    00274 fileDescriptor *fopen(const char *file,const char *flags) {
    00275   int             i          = 0x0;
    00276   char           *path       = 0x0;
    00277   char           *mountPoint = 0x0;
    00278   char            fileName[1024];
    00279   fileDescriptor *tmpFd      = 0x0;
    00280
    00281   /* Allocate Memory For File Descriptor */
    00282     if((tmpFd = (fileDescriptor *)kmalloc(sizeof(fileDescriptor))) == 0x0) {
    00283       kprintf("Error: tmpFd == NULL, File: %s, Line: %i\n",__FILE__,__LINE__);
    00284       return(NULL);
    00285     }
    00286
    00287   strcpy(fileName,file);
    00288
    00289   if (strstr(fileName,":")) {
    00290     mountPoint = (char *)strtok((char *)&fileName,":");
    00291     path = strtok(NULL,"\n");
    00292     }
    00293   else {
    00294     path = fileName;
    00295     }
    00296
    00297   if (path[0] == '/')
    00298     strcpy(tmpFd->fileName, path);
    00299   else
    00300     sprintf(tmpFd->fileName,"/%s",path);
    00301
    00302   /* Find our mount point or set default to sys */
    00303   if (mountPoint == 0x0)
    00304     tmpFd->mp = vfs_findMount("sys");
    00305   else
    00306     tmpFd->mp = vfs_findMount(mountPoint);
    00307
    00308   if (tmpFd->mp == 0x0) {
    00309     kprintf("Mount Point Bad\n");
    00310     return(0x0);
    00311     }
    00312
    00313   /* This Will Set Up The Descriptor Modes */
    00314   tmpFd->mode = 0;
    00315   for  (i = 0; '\0' != flags[i] ;i++ ) {
    00316     switch(flags[i]) {
    00317       case 'w':
    00318       case 'W':
    00319         tmpFd->mode |= fileWrite;
    00320         break;
    00321       case 'r':
    00322       case 'R':
    00323         tmpFd->mode |= fileRead;
    00324         break;
    00325       case 'b':
    00326       case 'B':
    00327         tmpFd->mode |= fileBinary;
    00328         break;
    00329       case 'a':
    00330       case 'A':
    00331         tmpFd->mode |= fileAppend;
    00332         break;
    00333       default:
    00334         kprintf("Invalid mode '%c' for fopen\n", flags[i]);
    00335         break;
    00336       }
    00337     }
    00338   /* Search For The File */
    00339   if (tmpFd->mp->fs->vfsOpenFile(tmpFd->fileName,tmpFd) == 0x1) {
    00340     /* If The File Is Found Then Set Up The Descriptor */
    00341
    00342
    00343    /* in order to save resources we will allocate the buffer later when it is needed */
    00344
    00345     tmpFd->buffer = (char *)kmalloc(4096);
    00346     if(tmpFd->buffer == 0x0)
    00347     {
    00348       kfree(tmpFd);
    00349       kprintf("Error: tmpFd->buffer == NULL, File: %s, Line: %i\n",__FILE__,__LINE__);
    00350       spinUnlock(&fdTable_lock);
    00351       return 0x1;
    00352     }
    00353     /* Set Its Status To Open */
    00354     tmpFd->status = fdOpen;
    00355
    00356     /* Initial File Offset Is Zero */
    00357     tmpFd->offset = 0;
    00358     tmpFd->prev = 0x0;
    00359
    00360    /* we do not want to be in a spinlock longer than we need to, so
    00361      it has been moved to here. */
    00362       spinLock(&fdTable_lock);
    00363
    00364     /* Increment Number Of Open Files */
    00365     systemVitals->openFiles++;
    00366
    00367     tmpFd->next = fdTable;
    00368
    00369     if (fdTable != 0x0)
    00370       fdTable->prev = tmpFd;
    00371
    00372      fdTable = tmpFd;
    00373
    00374       spinUnlock(&fdTable_lock);
    00375
    00376     /* Return The FD */
    00377     return(tmpFd);
    00378     }
    00379   else {
    00380     kfree(tmpFd->buffer);
    00381     kfree(tmpFd);
    00382     spinUnlock(&fdTable_lock);
    00383     kprintf("File Not Found? %s\n",file);
    00384     return (NULL);
    00385     }
    00386
    00387     /* Return NULL */
    00388     return(0x0);
    00389   }
    00390
    00391 /************************************************************************
    00392
    00393 Function: int fclose(fileDescriptor *fd);
    00394 Description: This Will Close And Free A File Descriptor
    00395 Notes:
    00396
    00397 ************************************************************************/
    00398 int fclose(fileDescriptor *fd) {
    00399   fileDescriptor *tmpFd = 0x0;
    00400   assert(fd);
    00401
    00402   spinLock(&fdTable_lock);
    00403
    00404   for (tmpFd = fdTable;tmpFd != 0x0;tmpFd = tmpFd->next) {
    00405     if (tmpFd == fd) {
    00406       if (tmpFd->prev)
    00407         tmpFd->prev->next = tmpFd->next;
    00408       if (tmpFd->next)
    00409         tmpFd->next->prev = tmpFd->prev;
    00410
    00411       if (tmpFd == fdTable)
    00412         fdTable = tmpFd->next;
    00413
    00414       systemVitals->openFiles--;
    00415       spinUnlock(&fdTable_lock);
    00416         if(tmpFd->buffer != NULL)
    00417                 kfree(tmpFd->buffer);
    00418       kfree(tmpFd);
    00419       return(0x0);
    00420       }
    00421     }
    00422
    00423   spinUnlock(&fdTable_lock);
    00424   return(0x1);
    00425   }
    00426
    00427 /* UBU */
    00428
    00429 /************************************************************************
    00430
    00431 Function: void sysMkDir(const char *path)
    00432 Description: This Will Create A New Directory
    00433 Notes:
    00434
    00435 ************************************************************************/
    00436 void sysMkDir(const char *path) {
    00437   fileDescriptor *tmpFD = 0x0;
    00438   char tmpDir[1024];
    00439   char rootPath[256];
    00440   char *dir = 0x0;//UBU*mountPoint = 0x0;
    00441   char *tmp = 0x0;
    00442   rootPath[0] = '\0';
    00443   dir = (char *)path;
    00444
    00445   if (strstr(path,":") == 0x0) {
    00446     sprintf(tmpDir,"%s%s",_current->oInfo.cwd,path);
    00447     dir = (char *)&tmpDir;
    00448     }
    00449   while (strstr(dir,"/")) {
    00450     if (rootPath[0] == 0x0)
    00451       sprintf(rootPath,"%s/",strtok(dir,"/"));
    00452     else
    00453       sprintf(rootPath,"%s%s/",rootPath,strtok(dir,"/"));
    00454     tmp = strtok(NULL,"\n");
    00455     dir = tmp;
    00456     }
    00457
    00458   //kprintf("rootPath: [%s]\n",rootPath);
    00459   tmpFD = fopen(rootPath,"rb");
    00460
    00461   if (tmpFD->mp == 0x0) {
    00462     kprintf("Invalid Mount Point\n");
    00463     }
    00464   tmpFD->mp->fs->vfsMakeDir(dir,tmpFD);
    00465
    00466   fclose(tmpFD);
    00467
    00468   return;
    00469   }
    00470
    00471
    00472 /************************************************************************
    00473
    00474 Function: int unlink(const char *node)
    00475 Description: This will unlink a file
    00476 Notes:
    00477
    00478 ************************************************************************/
    00479
    00480 int unlink(const char *node) {
    00481   char *path = 0x0,*mountPoint = 0x0;
    00482   struct vfs_mountPoint *mp = 0x0;
    00483
    00484   path = (char *)strtok((char *)node,"@");
    00485   mountPoint = strtok(NULL,"\n");
    00486   if (mountPoint == 0x0) {
    00487     mp = vfs_findMount("sys"); /* _current->oInfo.container; */
    00488     }
    00489   else {
    00490     mp = vfs_findMount(mountPoint);
    00491     }
    00492   if (mp == 0x0) {
    00493     //kpanic("Mount Point Bad");
    00494     return(0x0);
    00495     }
    00496   mp->fs->vfsUnlink(path,mp);
    00497   return(0x0);
    00498   }
    00499
    00500
    00501 /***
    00502  END
    00503  ***/
    00504