diff --git a/newfs_prodos.cpp b/newfs_prodos.cpp new file mode 100644 index 0000000..983bfed --- /dev/null +++ b/newfs_prodos.cpp @@ -0,0 +1,199 @@ +/* + * newfs_prodos.cpp + * ProFUSE + * + * Created by Kelvin Sherlock on 9/2/2009. + * + */ + +#include +#include +#include + +#include +#include + +#include +#include + +#define VERSION_STRING "0.1" + +void help(void) +{ + printf("newfs_prodos v %s\n", VERSION_STRING); + + printf("usage: newfs_prodos -N -s size -v volname file\n"); + printf("\t-N test mode (do not create)\n"); + printf("\t-s size file size in blocks (or use K/M)\n"); + printf("\t-v volname volume name"); + + exit(0); +} + + + //returns number of blocks. +long parseBlocks(const char *cp) +{ + long size; + char *end; + unsigned base = 0; + const char *ocp = cp; + + if (cp && *cp == '$') + { + base = 16; + cp++; + } + + if (!cp || !*cp) + { + fprintf(stderr, "Invalid size.\n"); + exit(1); + } + + size = strtol(cp, &end, base); + + if (end == cp) + { + fprintf(stderr, "Invalid size: `%s'\n", ocp); + exit(1); + } + + // number may be M, K, or null (blocks) + if (*end == 0) return size; + if (*end == 'K') return size << 1; + if (*end == 'M') return size << 10; + + fprintf(stderr, "Invalid size modifier: `%s'\n", end); + exit(1); + + return -1; +} + + +// verify a size is reasonable for a ProDOS volume +bool validBlocks(long blocks) +{ + if (blocks < 280) return false; + if (blocks > (32 << 10)) return false; + + return true; +} + +bool validName(const char *name) +{ + unsigned i; + + if (name == 0 || *name == 0) return false; + + for(i = 0; name[i]; ++i) + { + char c = name[i]; + + if (c == '.') continue; + if (c & 0x80) return false; + if (isdigit(c) && i) continue; + if (isalpha(c)) continue; + + return false; + } + + // i = strlen(name) + 1 + return i < 16; + +} + +const char *generateName(const char *src) +{ + // basename may alter it's argument. + + char * cp = strdup(src); + + cp = basename(cp); + + unsigned l = strlen(cp); + // remove any extension... + for (unsigned i = l; i; --i) + { + if (cp[i-1] == '.') + { + cp[i-1] = 0; + l = i - 1; + break; + } + } + if (validName(cp)) return cp; + + free(cp); + return "Untitled"; +} + +int main(int argc, char **argv) +{ + int ch; + bool fTest = false; + const char *fVolname = NULL; + const char *filename; + + long fBlocks = 800 << 1; + + + while ((ch = getopt(argc, argv, "hNs:v:")) != -1) + { + switch(ch) + { + case 'h': + default: + help(); + break; + + case 'N': + fTest = true; + break; + + case 'v': + fVolname = optarg; + break; + + + case 's': + fBlocks = parseBlocks(optarg); + break; + } + } + + // verify size is ok + if (!validBlocks(fBlocks)) + { + fprintf(stderr, "Invalid size. Please use 140K -- 32M\n"); + exit(1); + } + + if (fVolname && !validName(fVolname)) + { + fprintf(stderr, "Invalid volume name: `%s'.\n", fVolname); + exit(1); + } + + argv += optind; + argc -= optind; + + if (argc != 1) + { + help(); + } + filename = *argv; + + if (!fVolname) fVolname = generateName(filename); + + if (fTest) + { + printf(" Image Name: %s\n", filename); + printf("Volume Name: %s\n", fVolname); + printf("Volume Size: %u blocks (%uK)\n", fBlocks, fBlocks >> 1); + + exit(0); + } + + exit(0); +} \ No newline at end of file