This is the firmware for the LaOS - Laser Open Source project. You can use it to drive a laser cutter. For hardware and more information, look at our wiki: http://wiki.laoslaser.org

Dependencies:   EthernetNetIf mbed

LaosFile/laosfilesystem.cpp

Committer:
fablabtruck
Date:
2012-06-08
Revision:
0:3852426a5068

File content as of revision 0:3852426a5068:

/*
 *
 * LaosFilesystem.cpp
 * Simple Long Filename system on top of SDFilesystem.h
 *
 * Copyright (c) 2011 Jaap Vermaas
 *
 *   This file is part of the LaOS project (see: http://wiki.laoslaser.org
 *
 *   LaOS is free software: you can redistribute it and/or modify
 *   it under the terms of the GNU General Public License as published by
 *   the Free Software Foundation, either version 3 of the License, or
 *   (at your option) any later version.
 *
 *   LaOS is distributed in the hope that it will be useful,
 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *   GNU General Public License for more details.
 *
 *   You should have received a copy of the GNU General Public License
 *   along with LaOS.  If not, see <http://www.gnu.org/licenses/>.
 *
 */
#include "laosfilesystem.h"

LaosFileSystem::LaosFileSystem(PinName mosi, PinName miso, PinName sclk, PinName cs, const char* name)
        : SDFileSystem(mosi, miso, sclk, cs, name) {
    sprintf(tablename, "/%s/%s", name, _LAOSFILE_TRANSTABLE);
    sprintf(pathname, "/%s/", name);
}

LaosFileSystem::~LaosFileSystem() {
}

FILE* LaosFileSystem::openfile(char *name, char* iom) {
    if (islegalname(name)) {  // check length and chars in name

        char shortname[SHORTFILESIZE] = "";
        getshortname(shortname, name);
        char fullname[MAXFILESIZE+SHORTFILESIZE+1];
        if (strstr(iom, "r")) {        // open file for reading
            if (strlen(shortname)!=0) {
                sprintf(fullname, "%s%s", pathname, shortname);
                return fopen(fullname, iom);
            } else {                // no file exists
                return NULL;
            }
        } else {                    // open file for writng
            if (strlen(shortname)!=0) {
                sprintf(fullname, "%s%s", pathname, shortname);
                return fopen(fullname, iom);
            } else {                    // create a new file
                makeshortname(shortname, name);
                sprintf(fullname, "%s%s", pathname, shortname);
                return fopen(fullname, iom);
            }
        }
    } else {    // (islegalname(name))
        return NULL;
    }
}

void LaosFileSystem::getlongname(char *result, char *searchname) {
    FILE *fp = fopen(tablename, "r");
    if (fp) {
        char longname[MAXFILESIZE];
        char shortname[SHORTFILESIZE];
        while (dirread(longname, shortname, fp))
            if (! strcmp(shortname, searchname))
                break;
        if (strcmp(shortname, searchname))
            strcpy(result, searchname);
        else
            strcpy(result, longname);
        fclose(fp);
    } else {
        strcpy(result, searchname);
    }
}

int LaosFileSystem::islegalname(char* name) {
    if (( strlen(name) > MAXFILESIZE-1 ) || (strlen(name) == 0))
        return 0;
    int legal = 1;
    char nochar[] = "?*,;=+#>|[]/\\";
    int x = 0;
    while (legal && (name[x] != 0)) {
        legal *= (name[x] > 32) && (name[x] < 126);
        int y = 0;
        while (legal && (nochar[y] != 0))
            legal *= name[x] != nochar[y++];
        x++;
    }
    return legal;
}

int LaosFileSystem::isshortname(char* name) {
    int len = strlen(name);
    for (int x=0; x<len; x++)
        if (name[x] == ' ') return 0; // spaces not allowed in shortname

    char myname[MAXFILESIZE];
    strcpy(myname, name);
    char *basename = NULL;
    if (len <= SHORTFILESIZE-1) {
        basename = strtok(myname, ".");
        if (strlen(basename) > 8) {
            return 0;    // basename was too long
        } else {
            if (char *ext_name = strtok(NULL, ".")) {  //
                if ((strlen(basename)+strlen(ext_name)+1) == len) {
                    if (strlen(ext_name)<4) {
                        return 1; // filename is in 8.3 format
                    } else {
                        return 0; // extension too long
                    }
                } else {
                    return 0; // there was more then one dot
                }
            } else {
                return 1; // filename of max 8 chars, no extension (OK)
            }
        }
    } else {
        return 0; // total filename too long
    }
}

void LaosFileSystem::removespaces(char* name) {
    int spaces = 1;
    while (spaces) {
        spaces = 0;
        int x = 0;
        while ((name[x] != ' ') && (x<strlen(name))) x++;
        if (name[x] == ' ') {
            spaces = 1;
            for (int y = x; x<(strlen(name)-1); y++)
                name[y] = name[y+1];
        }
    }
}

void LaosFileSystem::getshortname(char* shortname, char* name) {
    // * open filename translation table
    // * and see if a file with that name exists
    if (isshortname(name)) {
        strcpy(shortname, name);
    } else {
        int found = 0;
        char longname[MAXFILESIZE];
        FILE *fp = fopen(tablename, "r");
        if (fp) {
            while (dirread(longname, shortname, fp)) {
                if (!strcmp(longname, name)) {
                    found = 1;
                    break;
                }
            }
            if (! found) strcpy(shortname, "");
            fclose(fp);
        }
    }
}

void LaosFileSystem::makeshortname(char* shortname, char* name) {
    char *tmpname = new char[MAXFILESIZE];
    strcpy(tmpname, name);
    removespaces(tmpname);
    shorten(tmpname, SHORTFILESIZE);
    char *basename = strtok(tmpname, ".");
    char *ext_name = strtok(NULL, ".");
    strtolower(basename);
    strtolower(ext_name);
    int cnt = 1;
    char fullname[MAXFILESIZE+SHORTFILESIZE+2];
    FILE *fp = NULL;
    do {
        if (fp != NULL) fclose(fp);
        while ((cnt/10+strlen(basename)+2) > 8)
            basename[strlen(basename)-1] = 0;
        if (strlen(ext_name) > 0) {
            sprintf(shortname, "%s~%d.%s", basename, cnt++, ext_name);
        } else {
            sprintf(shortname, "%s~%d", basename, cnt++);
        }
        sprintf(fullname, "%s%s", pathname, shortname);
        fp = fopen(fullname, "rb");
    } while (fp!=NULL);
    
    FILE *tfp = fopen(tablename, "ab");
    dirwrite(name, shortname, tfp);
    fclose(tfp);

    delete(tmpname);
}

void LaosFileSystem::cleanlist() {
    // * open filename translation table
    char longname[MAXFILESIZE];
    char shortname[SHORTFILESIZE];
    char tabletmpname[MAXFILESIZE+SHORTFILESIZE+1];
    strcpy (tabletmpname, tablename);
    tabletmpname[strlen(tabletmpname)-1] = '~';
    
    // make a full copy of the table
    FILE* fp1 = fopen(tablename, "rb");
    if (fp1 == NULL) return;
    FILE* fp2 = fopen(tabletmpname, "wb");
    if (fp2 == NULL) return;
    while (dirread(longname, shortname, fp1))
        dirwrite(longname, shortname, fp2);
    fclose(fp1);
    fclose(fp2);

    fp1 = fopen(tablename, "wb");
    if (fp1 == NULL) return;
    fp2 = fopen(tabletmpname, "rb");
    if (fp2 == NULL) return;
    FILE* fp;
    while (dirread(longname, shortname, fp2)) {
        char fullname[MAXFILESIZE+SHORTFILESIZE+1];
        sprintf(fullname, "%s%s", pathname, shortname);
        fp = fopen(fullname, "rb");
        if (fp != NULL) {
            fclose(fp);
            dirwrite(longname, shortname, fp1);
        } 
     }
     fclose(fp1);
     fclose(fp2);
}

void LaosFileSystem::shorten(char* name, int max) {
    int len = 0;
    while (name[len++] != 0);   /* end of string */
    len--;
    if (len > max-1) {
        int ext = len;
        while (name[--ext] != '.'); /* begin of extension */
        int baselen, extlen;
        baselen = ext;
        extlen = len-ext-1;
        while ((baselen > max-5) && (baselen+extlen+1 > max-1))
            baselen--;
        name[baselen++] = '.';
        while ((ext<len) && (baselen < max-1))
            name[baselen++] = name[++ext];
        name[baselen] = 0;
    }
}

size_t LaosFileSystem::dirread(char* longname, char* shortname, FILE *fp) {
    char buff[MAXFILESIZE+SHORTFILESIZE];
    size_t result = fread(buff, 1, MAXFILESIZE+SHORTFILESIZE, fp);
    if (result) {       
        strncpy(longname, buff, MAXFILESIZE);
        longname[MAXFILESIZE-1] = 0;
        int cnt = MAXFILESIZE-2;
        while (longname[cnt]==' ') longname[cnt--] = 0;
        
        strncpy(shortname, &buff[MAXFILESIZE], SHORTFILESIZE);
        shortname[SHORTFILESIZE-1] = 0;
        cnt = SHORTFILESIZE-2;
        while (shortname[cnt]==' ') shortname[cnt--] = 0;
    }
    return result;
}

size_t LaosFileSystem::dirwrite(char* longname, char* shortname, FILE* fp) {
    char buff[MAXFILESIZE+SHORTFILESIZE];
    int x=0; 
    while (longname[x] != 0) buff[x++] = longname[x];
    while (x<MAXFILESIZE-1) buff[x++] = ' ';
    buff[x++] = '\t';
    while (shortname[x-MAXFILESIZE] != 0) buff[x++] = shortname[x-MAXFILESIZE];
    while (x<MAXFILESIZE+SHORTFILESIZE-1) buff[x++] = ' ';
    buff[x++] = '\n';
    
    return fwrite(buff, 1, MAXFILESIZE+SHORTFILESIZE, fp);
}

void showfile() {
    char buff[35];
    FILE *fp = fopen("/sd/longname.sys","rb");
    if (fp) {
        printf("Contents of longname.sys\n\r");
        while (fread(buff, 1, MAXFILESIZE+SHORTFILESIZE, fp))
            printf("> %s\r", buff);
        fclose(fp);
        printf("\n\r");
    }
}

void cleandir() {
    DIR *d;
    struct dirent *p;
    d = opendir("/sd");
    if(d != NULL) {
        while((p = readdir(d)) != NULL) {
            char fullname[MAXFILESIZE+SHORTFILESIZE+2];
            sprintf(fullname, "/sd/%s", p->d_name);
            remove(fullname);
        }
    } else {
        error("Could not open directory!\n\r");
    }
}

void printdir() {
    extern LaosFileSystem sd;
    printf("List of files in /sd\n\r");
    DIR *d;
    struct dirent *p;
    d = opendir("/sd");
    if(d != NULL) {
        // printf("...\n\r");
        while((p = readdir(d)) != NULL) {
            // printf("Short %s\n\r", p->d_name);
            if (strncmp(p->d_name, "longname.sy",11)) {
                char longname[MAXFILESIZE];
                // printf("Getlongname\n\r");
                sd.getlongname(longname, p->d_name);
                printf(" - %s (short: %s)\n\r", longname, p->d_name);
            }
        }
    } else {
        printf("Could not open directory!\n\r");
    }
}

void getprevjob(char *name) {
    extern LaosFileSystem sd;
    char shortname[SHORTFILESIZE], last[SHORTFILESIZE];
    strcpy(last, "");
    sd.getshortname(shortname, name);
    DIR *d;
    struct dirent *p;
    d = opendir("/sd");
    if(d != NULL) {
        while((p = readdir(d)) != NULL) {
            if (strncmp(p->d_name, "longname.sy",11)) { // skip longname.sy*
                if (! strcmp(shortname, p->d_name)) {   // shortname = current entry
                    if (strcmp(last, "")) {
                        sd.getlongname(name, last);     // return entry before
                    } else {
                        sd.getlongname(name, p->d_name);    // last="", so current = first
                    }
                    closedir(d);
                    return;
                }
                strcpy(last, p->d_name);
            }
        } // while
        closedir(d);
    } else {
        printf("Getfilename: Could not open directory!\n\r");
    }
    sd.getlongname(name, last); // name not found (return last) 
                                // or no file found (return "") 
}

void getnextjob(char *name) {
    extern LaosFileSystem sd;
    char shortname[SHORTFILESIZE], last[SHORTFILESIZE];
    strcpy(last, "");
    sd.getshortname(shortname, name);
    DIR *d;
    struct dirent *p;
    d = opendir("/sd");
    if(d != NULL) {
        while((p = readdir(d)) != NULL) {
            if (strncmp(p->d_name, "longname.sy",11)) { // skip longname.sy*
                if (! strcmp(shortname, last)) {        // if last was shortname
                    sd.getlongname(name, p->d_name);    //    return current
                    closedir(d);
                    return;
                }
                strcpy(last, p->d_name);
            }
        } // while
        closedir(d);
    } else {
        printf("Getfilename: Could not open directory!\n\r");
    }
    sd.getlongname(name, last);     // if last file was match, return the last
                                    // if filename not found, return last
                                    // if no file in directory, return ""
}

/*
void getfilename(char *name, int filenr) {
    extern LaosFileSystem sd;
    int cnt=0;
    DIR *d;
    struct dirent *p;
    d = opendir("/sd");
    if(d != NULL) {
        while((p = readdir(d)) != NULL) {
            if (strncmp(p->d_name, "longname.sy",11)) {
                if (cnt++ == filenr) {
                    sd.getlongname(name, p->d_name);
                    closedir(d);
                    return;
                }
            }
        } // while
        strcpy(name, "");
        closedir(d);
    } else {
        printf("Getfilename: Could not open directory!\n\r");
    }
}

int getfilenum(char *name) {
    extern LaosFileSystem sd;
    char shortname[SHORTFILESIZE];
    getshortname(shortname, name);
    int cnt=0;
    DIR *d;
    struct dirent *p;
    d = opendir("/sd");
    if(d != NULL) {
        while((p = readdir(d)) != NULL) {
            if (strncmp(p->d_name, "longname.sy",11)) {
                if (!strcmp(shortname, name)) {
                    closedir(d);
                    return cnt;
                }
                cnt++;
            }
        } // while
        closedir(d);
        return 0;
    } else {
        printf("Getfilename: Could not open directory!\n\r");
    }
    return 0;
}
*/

void writefile(char *myfile) {
    extern LaosFileSystem sd;
    printf("Writing file %s\n\r", myfile);
    FILE *fp = sd.openfile(myfile, "wb");
    if (fp) {
        fclose(fp);
    } 
}

void removefile(char *name) {
    extern LaosFileSystem sd;
    char shortname[SHORTFILESIZE] = "";
    sd.getshortname(shortname, name);
    if (strlen(shortname) != 0) {
        char fullname[MAXFILESIZE+SHORTFILESIZE+1];
        sprintf(fullname, "%s%s", sd.pathname, shortname);
        if (remove(fullname) < 0)
            printf("Error while removing file %s\n\r", fullname);
        sd.cleanlist();           
    } 
}

// Read an integer from file
int readint(FILE *fp)
{
  unsigned short int i=0;
  int sign=1;
  char c, str[16];
  
  while( !feof(fp)  )
  {
    fread(&c, sizeof(c),1,fp);   
    
    switch(c)
    {
      case '0': case '1': case '2':  case '3':  case '4': 
      case '5': case '6': case '7':  case '8':  case '9':  
        if ( i < sizeof(str)) 
          str[i++] = (char)c;
        break;
      case '-': sign = -1; break;
      case ';': while ((!feof(fp)) && (c != '\n')) {
            fread(&c, sizeof(c),1,fp);
        }
        break; 
      case ' ': case '\t': case '\r': case '\n':
        if ( i )
        {
          int val=0, d=1;
          while(i) 
          {
            if ( str[i-1] == '-' ) 
              d *= -1;
            else
              val += (str[i-1]-'0') * d;
            d *= 10;
            i--;
          }
          val *= sign;
          return val;
        }
        break;
    } // Switch
  } // while
  return 0;
} // read integer

void strtolower(char *name) {
    for(int i = 0; i < strlen(name); i++)
        name[i] = tolower(name[i]);
}

int isFirmware(char *filename) {
    char name[MAXFILESIZE];
    strcpy(name, filename);
    strtolower(name);
    int x = strlen(name);
    if ((tolower(filename[--x])=='n') && (tolower(filename[--x])=='i') && (tolower(filename[--x])=='b') && (filename[--x]=='.'))
        return 1;
    else
        return 0;
} 

void installFirmware(char *filename) {
    removeFirmware();
    char buff[512];
    extern LaosFileSystem sd;
    //printf("Copy firmware file %s\n\r", filename);
    FILE *fp = sd.openfile(filename, "rb");
    if (fp) {
        FILE *fp2 = fopen("/local/firmware.bin", "wb");
        while (!feof(fp)) {
            int size = fread(buff, 1, 512, fp);
            fwrite(buff, 1, size, fp2);
        }
        fclose(fp);
        fclose(fp2);
    }
    removefile(filename);
}

void removeFirmware() { // remove old firmware from SD
    DIR *d;
    struct dirent *p;
    d = opendir("/local");
    if(d != NULL) {
        while((p = readdir(d)) != NULL) {
            if (isFirmware(p->d_name)) {
                char name[32];
                sprintf(name, "/local/%s", p->d_name);
                remove(name);
            } 
        }
    } else {
        printf("removeFirmware: Could not open directory!\n\r");
    }
}

int SDcheckFirmware() {
    extern LaosFileSystem sd;
    DIR *d;
    struct dirent *p;
    d = opendir("/sd");
    if(d != NULL) {
        while((p = readdir(d)) != NULL) {
            if (strncmp(p->d_name, "longname.sy",11)) {
                if (isFirmware(p->d_name)) {
                    installFirmware(p->d_name);
                    return 1;
                }
            }
        }
    } else {
        printf("SDcheckFirmware: Could not open directory!\n\r");
    }
    return 0;
}

int isLaosFile(char *filename) {
    char name[MAXFILESIZE];
    strcpy(name, filename);
    strtolower(name);
    int x = strlen(name);
    if ((tolower(filename[--x])=='c') && (tolower(filename[--x])=='g') && (tolower(filename[--x])=='l') && (filename[--x]=='.'))
        return 1;
    else
        return 0;
}