/* vrfile.c - file list functions Copyright (C) 2001 Jeff Carneal This program 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 2 of the License, or (at your option) any later version. This program 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 this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "config.h" #include #include #include #include #include #include #include #include "vrfile.h" #include "vrerror.h" VRFILE *first=NULL; /* * Add a file to transfer * to the end of list */ void vrfile_add(VRFILE *new) { VRFILE *cur; if(first) { for(cur=first; cur->next; cur=cur->next); cur->next = new; } else { first = new; } } /* * This is for debugging only */ void vrfile_list(void) { VRFILE *cur; for(cur=first; cur; cur=cur->next) { fprintf(stderr, "NAME: %s\n", cur->filename); fprintf(stderr, "OFFSET: 0x%lx\n", cur->offset); fprintf(stderr, "SIZE: 0x%lx (0x%lx)\n", cur->size, SECTOR_ALIGN(cur->size)); fprintf(stderr, "TEMP: %d\n", cur->tempfile); fprintf(stderr, "FLASH: flash 80090000 %lx %lx\n\n", SECTOR_ALIGN(cur->size), cur->offset); } } /* * Remove the temp files we * created (if any) */ void vrfile_cleanup(int retval) { VRFILE *cur; for(cur=first; cur; cur=cur->next) { if(cur->tempfile) { fprintf(stderr, "Cleanup removing %s ...", cur->filename); unlink(cur->filename); fprintf(stderr, "done\n"); } } exit(retval); } /* * Do misc checks on the input file */ void vrfile_chk(VRFILE *vrptr, CONFIG *conf) { struct stat st; if(strstr(vrptr->filename, ".srec")) { fprintf(stderr,"\n\tError: This looks like an srec file.\n" "\tUse mipsel-linux-objcopy to convert the file \n" "\tto binary format and then run vrflash again.\n\n"); vr_error("\tOh, and read the documentation."); } /* * Make sure file exists */ if(stat(vrptr->filename, &st)<0) { vr_error("Error: unable to stat %s", vrptr->filename); } vrptr->size = st.st_size; /* * Check for oversized kernel */ if((vrptr->offset==0) && conf->chkromsize && (vrptr->size>MAX_KERNEL_SIZE)) { vr_error("Error: kernel '%s' is larger than 0x%lx bytes. Aborting.", vrptr->filename, MAX_KERNEL_SIZE); } /* * Check for oversized romdisk */ if((vrptr->offset>0) && conf->chkkernsize && (vrptr->size>MAX_ROMDISK_SIZE)) { vr_error("Error: romdisk '%s' is larger than 0x%lx bytes. Aborting.", vrptr->filename, MAX_ROMDISK_SIZE); } /* * See if we need to split the file * to fit it into the vr3's RAM */ if((vrptr->offset>0) && (vrptr->size>MAX_DOWNLOAD_SIZE)) { fprintf(stderr, "Romdisk larger than 0x%lx. Splitting into:\n", (long)MAX_DOWNLOAD_SIZE); if(conf->tmpdir) { vrfile_split(vrptr, conf->tmpdir); } else { vrfile_split(vrptr, TMPDIR); } } } /* * Split current file into two smaller * files for downloading */ void vrfile_split(VRFILE *vrptr, char *tmp) { int len=0; int fd=0; int splitfd=0; int ret=0; int wtotal=0; int oldsize=0; char *fnameptr; char *splitfile; unsigned char buf[BUFSIZE]; struct stat st; VRFILE *new; /* * Get the last piece of the * input file name */ fnameptr = strrchr(vrptr->filename, '/'); if(fnameptr) fnameptr++; else fnameptr = vrptr->filename; /* * Make sure tmp dir does * not end * with a '/' */ len=strlen(tmp) - 1; if(tmp[len] == '/') tmp[len] = 0; if(stat(tmp,&st)<0) vr_error("Error: unable to stat '%s'", tmp); if(!S_ISDIR(st.st_mode)) vr_error("Error: '%s' is not a directory", tmp); len = strlen(tmp)+strlen(fnameptr)+4; splitfile = (char *)malloc(len); memset(splitfile, 0, len); snprintf(splitfile, len, "%s/%s.1", tmp, fnameptr); if(!(fd = open(vrptr->filename, O_RDONLY))) { vr_error("Error: Can't open '%s' for reading", vrptr->filename); } if(!(splitfd = open(splitfile, O_CREAT|O_TRUNC|O_WRONLY, 0644))) { vr_error("Error: Can't open '%s' for writing", splitfile); } fprintf(stderr, " %s ...",splitfile); while((ret=read(fd,buf,BUFSIZE))==BUFSIZE) { if((wtotal+BUFSIZE) <= SPLITFILE_OFFSET) { wtotal+=BUFSIZE; write(splitfd, buf, BUFSIZE); } else { write(splitfd, buf, (SPLITFILE_OFFSET-wtotal)); wtotal = SPLITFILE_OFFSET; } if(wtotal==SPLITFILE_OFFSET) { close(splitfd); break; } } if(ret<=0) vr_error("Error: unable to read from '%s' (%d)", vrptr->filename, ret); fprintf(stderr, "done (size = 0x%lx)\n", (long)SPLITFILE_OFFSET); /* * Now create second file */ new = (VRFILE *)malloc(sizeof(VRFILE)); if(!new) vr_error("Error: out of memory"); memset(new,0,sizeof(VRFILE)); /* * Setup old and new vrfile with * post-split settings */ oldsize = vrptr->size; vrptr->filename = strdup(splitfile); vrptr->tempfile = 1; vrptr->size = SPLITFILE_OFFSET; if(stat(splitfile,&st)<0) vr_error("Error: unable to stat '%s'", splitfile); if(st.st_size != vrptr->size) vr_error("Error: '%s' should be 0x%lx bytes long but is 0x%lx", splitfile, SPLITFILE_OFFSET, st.st_size); snprintf(splitfile, len, "%s/%s.2", tmp, fnameptr); new->filename = strdup(splitfile); new->offset = vrptr->offset + SPLITFILE_OFFSET; new->size = oldsize - SPLITFILE_OFFSET; new->tempfile = 1; /* * Add new split file to the * files list */ new->next = vrptr->next; vrptr->next = new; /* * Write second file */ if(!(splitfd = open(new->filename, O_CREAT|O_TRUNC|O_WRONLY, 0644))) { vr_error("Error: Can't open '%s' for writing", new->filename); } if(lseek(fd, SPLITFILE_OFFSET, SEEK_SET) < 0) { vr_error("Error: Can't seek to byte 0x%lx of '%s'", SPLITFILE_OFFSET, vrptr->filename); } fprintf(stderr, " %s ...",new->filename); while((ret=read(fd,buf,BUFSIZE))>0) { if(ret==BUFSIZE) { if(write(splitfd, buf, BUFSIZE)<0) vr_error("Error: unable to write to '%s'", new->filename); } else if(retfilename); break; } } if(ret < 0) vr_error("Error: unable to read from '%s'", vrptr->filename); fprintf(stderr, "done (size = 0x%lx)\n\n", new->size); if(stat(new->filename,&st)<0) vr_error("Error getting info for '%s'", new->filename); if(st.st_size != new->size) vr_error("Error: '%s' should be 0x%lx bytes long but is 0x%lx", new->filename, SPLITFILE_OFFSET, st.st_size); if(st.st_size > MAX_DOWNLOAD_SIZE) vr_error("Error: '%s' still too big for vr3 download.", new->filename); free(splitfile); close(splitfd); close(fd); }