// given a filename, compute its path in a directory hierarchy // If create is true, create the directory if needed // int dir_hier_path( const char* filename, const char* root, int fanout, char* path, bool create ) { char dir[256], dirpath[MAXPATHLEN]; int retval; if (fanout==0) { sprintf(path, "%s/%s", root, filename); return 0; } filename_hash(filename, fanout, dir); sprintf(dirpath, "%s/%s", root, dir); if (create) { retval = boinc_mkdir(dirpath); if (retval && (errno != EEXIST)) { fprintf(stderr, "boinc_mkdir(%s): %s: errno %d\n", dirpath, boincerror(retval), errno ); return ERR_MKDIR; } } sprintf(path, "%s/%s", dirpath, filename); return 0; }
SerialFlashFile SerialFlashChip::open(const char *filename) { uint32_t maxfiles, straddr; uint16_t hash, hashtable[8]; uint32_t i, n, index=0; uint32_t buf[3]; SerialFlashFile file; maxfiles = check_signature(); //Serial.printf("sig: %08X\n", maxfiles); if (!maxfiles) return file; maxfiles &= 0xFFFF; hash = filename_hash(filename); //Serial.printf("hash %04X for \"%s\"\n", hash, filename); while (index < maxfiles) { n = 8; if (n > maxfiles - index) n = maxfiles - index; SerialFlash.read(8 + index * 2, hashtable, n * 2); //Serial.printf(" read %u: ", 8 + index * 2); //pbuf(hashtable, n * 2); for (i=0; i < n; i++) { if (hashtable[i] == hash) { //Serial.printf(" hash match at index %u\n", index+i); buf[2] = 0; SerialFlash.read(8 + maxfiles * 2 + (index+i) * 10, buf, 10); //Serial.printf(" maxf=%d, index=%d, i=%d\n", maxfiles, index, i); //Serial.printf(" read %u: ", 8 + maxfiles * 2 + (index+i) * 10); //pbuf(buf, 10); straddr = 8 + maxfiles * 12 + buf[2] * 4; //Serial.printf(" straddr = %u\n", straddr); if (filename_compare(filename, straddr)) { //Serial.printf(" match!\n"); //Serial.printf(" addr = %u\n", buf[0]); //Serial.printf(" len = %u\n", buf[1]); file.address = buf[0]; file.length = buf[1]; file.offset = 0; file.dirindex = index + i; return file; } } else if (hashtable[i] == 0xFFFF) { return file; } } index += n; } return file; }
// same, but the output is a URL (used by tools/backend_lib.C) // int dir_hier_url( const char* filename, const char* root, int fanout, char* result ) { char dir[256]; if (fanout==0) { sprintf(result, "%s/%s", root, filename); return 0; } filename_hash(filename, fanout, dir); sprintf(result, "%s/%s/%s", root, dir, filename); return 0; }
bool SerialFlashChip::create(const char *filename, uint32_t length, uint32_t align) { uint32_t maxfiles, stringsize; uint32_t index, buf[3]; uint32_t address, straddr, len; SerialFlashFile file; // check if the file already exists if (exists(filename)) return false; // first, get the filesystem parameters maxfiles = check_signature(); if (!maxfiles) return false; stringsize = (maxfiles & 0xFFFF0000) >> 14; maxfiles &= 0xFFFF; // find the first unused slot for this file index = find_first_unallocated_file_index(maxfiles); if (index >= maxfiles) return false; //Serial.printf("index = %u\n", index); // compute where to store the filename and actual data straddr = 8 + maxfiles * 12; if (index == 0) { address = straddr + stringsize; } else { buf[2] = 0; SerialFlash.read(8 + maxfiles * 2 + (index-1) * 10, buf, 10); address = buf[0] + buf[1]; straddr += buf[2] * 4; straddr += string_length(straddr); straddr = (straddr + 3) & 0x0003FFFC; } //Serial.printf("straddr = %u\n", straddr); //Serial.printf("address = %u\n", address); //Serial.printf("length = %u\n", length); if (align > 0) { // for files aligned to sectors, adjust addr & len address += align - 1; address /= align; address *= align; //Serial.printf("align address = %u\n", address); length += align - 1; length /= align; length *= align; //Serial.printf("align length = %u\n", length); } else { // always align every file to a page boundary // for predictable write latency and to guarantee // write suspend for reading another file can't // conflict on the same page (2 files never share // a write page). address = (address + 255) & 0xFFFFFF00; } //Serial.printf("address = %u\n", address); // last check, if enough space exists... len = strlen(filename); // TODO: check for enough string space for filename // 5 bytes, to allow for extra 2 bytes in Spansion device IDs uint8_t id[5]; SerialFlash.readID(id); if (address + length > SerialFlash.capacity(id)) return false; SerialFlash.write(straddr, filename, len+1); buf[0] = address; buf[1] = length; buf[2] = (straddr - (8 + maxfiles * 12)) / 4; SerialFlash.write(8 + maxfiles * 2 + index * 10, buf, 10); //Serial.printf(" write %u: ", 8 + maxfiles * 2 + index * 10); //pbuf(buf, 10); while (!SerialFlash.ready()) ; // TODO: timeout buf[0] = filename_hash(filename); //Serial.printf("hash = %04X\n", buf[0]); SerialFlash.write(8 + index * 2, buf, 2); while (!SerialFlash.ready()) ; // TODO: timeout return true; }