aboutsummaryrefslogtreecommitdiff
path: root/libmpio/directory.c
diff options
context:
space:
mode:
authorsalmoon <salmoon>2002-08-28 16:10:44 +0000
committersalmoon <salmoon>2002-08-28 16:10:44 +0000
commit0d8d92cf4631f4a0a88fe04817d375f9e73408e4 (patch)
tree66c43b0aec21aaa2ea6643fe38b71fac12b91fe4 /libmpio/directory.c
downloadmpiosh-0d8d92cf4631f4a0a88fe04817d375f9e73408e4.tar.gz
mpiosh-0d8d92cf4631f4a0a88fe04817d375f9e73408e4.tar.bz2
mpiosh-0d8d92cf4631f4a0a88fe04817d375f9e73408e4.zip
Initial revision
Diffstat (limited to 'libmpio/directory.c')
-rw-r--r--libmpio/directory.c509
1 files changed, 509 insertions, 0 deletions
diff --git a/libmpio/directory.c b/libmpio/directory.c
new file mode 100644
index 0000000..b14dd6d
--- /dev/null
+++ b/libmpio/directory.c
@@ -0,0 +1,509 @@
+/*
+ *
+ * $Id: directory.c,v 1.1 2002/08/28 16:10:51 salmoon Exp $
+ *
+ * Library for USB MPIO-*
+ *
+ * Markus Germeier (mager@tzi.de)
+ *
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ *
+ * */
+
+#include <unistd.h>
+#include <iconv.h>
+
+#include "debug.h"
+#include "io.h"
+#include "mpio.h"
+#include "directory.h"
+
+/* directory operations */
+BYTE *
+mpio_directory_open(mpio_t *m, BYTE mem)
+{
+ BYTE *out;
+ if (mem == MPIO_EXTERNAL_MEM) {
+ if (m->external.id) {
+ out = m->external.dir;
+ } else {
+ return NULL;
+ }
+ } else {
+ out = m->internal.dir;
+ }
+
+ if (out[0] == 0x00)
+ return NULL;
+
+ return out;
+}
+
+int
+mpio_dentry_get_size(mpio_t *m, BYTE *buffer)
+{
+ mpio_dir_entry_t *dentry;
+
+ if (!buffer)
+ return -1;
+
+ UNUSED(m);
+
+ dentry = (mpio_dir_entry_t *)buffer;
+
+ if ((dentry->name[0] & 0x40) &&
+ (dentry->attr == 0x0f) &&
+ (dentry->start[0] == 0x00) &&
+ (dentry->start[1] == 0x00)) {
+ dentry++;
+ while ((dentry->attr == 0x0f) &&
+ (dentry->start[0] == 0x00) &&
+ (dentry->start[1] == 0x00)) {
+ /* this/these are vfat slots */
+ dentry++;
+ }
+ }
+ dentry++;
+
+ return(((BYTE *)dentry) - buffer);
+}
+
+BYTE*
+mpio_dentry_next(mpio_t *m, BYTE *buffer)
+{
+ int size;
+ BYTE *out;
+
+ size = mpio_dentry_get_size(m, buffer);
+ if (size<0)
+ return NULL;
+
+ out = buffer + size;
+
+ if (*out == 0x00)
+ return NULL;
+
+ return out;
+}
+
+int
+mpio_dentry_get_raw(mpio_t *m, BYTE *dentry, BYTE *buffer, int bufsize)
+{
+ int size;
+
+ size = mpio_dentry_get_size(m, buffer);
+
+ if (size < 0)
+ return size;
+
+ if (size > bufsize)
+ return -2;
+
+ memcpy(buffer, dentry, size);
+
+ return size;
+}
+
+void
+mpio_dentry_copy_from_slot(BYTE *buffer, mpio_dir_slot_t *slot)
+{
+ memcpy(buffer, slot->name0_4, 10);
+ memcpy(buffer + 10, slot->name5_10, 12);
+ memcpy(buffer + 22, slot->name11_12, 4);
+}
+
+void
+mpio_dentry_copy_to_slot(BYTE *buffer, mpio_dir_slot_t *slot)
+{
+ memcpy(slot->name0_4, buffer, 10);
+ memcpy(slot->name5_10, buffer + 10, 12);
+ memcpy(slot->name11_12, buffer + 22, 4);
+}
+
+int
+mpio_dentry_get(mpio_t *m, BYTE *buffer,
+ BYTE *filename, int filename_size,
+ WORD *year, BYTE *month, BYTE *day,
+ BYTE *hour, BYTE *minute, DWORD *fsize)
+{
+ BYTE filename_8_3[12];
+
+ return mpio_dentry_get_real(m, buffer, filename, filename_size,
+ filename_8_3,
+ year, month, day, hour, minute, fsize);
+}
+
+/* TODO: please clean me up !!! */
+int
+mpio_dentry_get_real(mpio_t *m, BYTE *buffer,
+ BYTE *filename, int filename_size,
+ BYTE filename_8_3[12],
+ WORD *year, BYTE *month, BYTE *day,
+ BYTE *hour, BYTE *minute, DWORD *fsize)
+{
+ int date, time;
+ int vfat = 0;
+ int num_slots = 0;
+ int slots = 0;
+ int in = 0, out = 0;
+ mpio_dir_entry_t *dentry;
+ mpio_dir_slot_t *slot;
+ BYTE *unicode = 0;
+ BYTE *uc;
+ BYTE *fname = 0;
+ iconv_t ic;
+
+ if (buffer == NULL)
+ return -1;
+
+ dentry = (mpio_dir_entry_t *)buffer;
+
+ if ((dentry->name[0] & 0x40) &&
+ (dentry->attr == 0x0f) &&
+ (dentry->start[0] == 0x00) &&
+ (dentry->start[1] == 0x00)) {
+ num_slots = (mpio_dentry_get_size(m, buffer) / 0x20) - 1;
+ slots = num_slots - 1;
+ dentry++;
+ vfat++;
+ unicode = malloc(256);
+ uc = unicode;
+ fname = filename;
+ slot = (mpio_dir_slot_t *)buffer;
+ mpio_dentry_copy_from_slot(unicode + (26 * slots), slot);
+ slots--;
+
+ while ((dentry->attr == 0x0f) &&
+ (dentry->start[0] == 0x00) &&
+ (dentry->start[1] == 0x00)) {
+ /* this/these are vfat slots */
+ slot = (mpio_dir_slot_t *)dentry;
+ mpio_dentry_copy_from_slot((unicode + (26 * slots)), slot);
+ dentry++;
+ slots--;
+ }
+ }
+
+ if (vfat) {
+ ic = iconv_open("ASCII", "UNICODE");
+ in = num_slots * 26;
+ out = num_slots * 13;
+ memset(fname, 0, filename_size);
+ iconv(ic, (char **)&uc, &in, (char **)&fname, &out);
+ iconv_close(ic);
+ free(unicode);
+ } else {
+ memcpy(filename_8_3, dentry->name, 8);
+ filename_8_3[0x08] = '.';
+ memcpy(filename_8_3 + 0x09, dentry->ext, 3);
+ filename_8_3[0x0c] = 0;
+
+ if (filename_size >= 12) {
+ snprintf(filename, 13, "%s", filename_8_3);
+ } else {
+ snprintf(filename, 12, "%s", "ERROR");
+ }
+
+ }
+
+ date = (dentry->date[1] * 0x100) + dentry->date[0];
+ *year = date / 512 + 1980;
+ *month = (date / 32) & 0xf;
+ *day = date & 0x1f;
+
+ time = (dentry->time[1] * 0x100) + dentry->time[0];
+ *hour = time / 2048;
+ *minute= (time / 32) & 0x3f;
+
+ *fsize = dentry->size[3];
+ *fsize *= 0x100;
+ *fsize += dentry->size[2];
+ *fsize *= 0x100;
+ *fsize += dentry->size[1];
+ *fsize *= 0x100;
+ *fsize += dentry->size[0];
+
+ return(((BYTE *)dentry) - buffer);
+}
+
+/* read "size" sectors of fat into the provided buffer */
+int
+mpio_rootdir_read (mpio_t *m, mpio_mem_t mem)
+{
+ mpio_smartmedia_t *sm;
+ BYTE recvbuff[SECTOR_SIZE];
+ int i;
+
+ if (mem == MPIO_INTERNAL_MEM) sm = &m->internal;
+ if (mem == MPIO_EXTERNAL_MEM) sm = &m->external;
+
+ for (i = 0; i < DIR_NUM; i++) {
+ if (mpio_io_sector_read(m, mem,
+ (sm->dir_offset + i), sm->size, 0, recvbuff))
+ return 1;
+
+ memcpy(sm->dir + (i * SECTOR_SIZE), recvbuff, SECTOR_SIZE);
+ }
+
+ return (0);
+}
+
+int
+mpio_rootdir_clear (mpio_t *m, mpio_mem_t mem)
+{
+ mpio_smartmedia_t *sm;
+
+ if (mem == MPIO_INTERNAL_MEM) sm=&m->internal;
+ if (mem==MPIO_EXTERNAL_MEM) sm=&m->external;
+
+ memset(sm->dir, 0x00, DIR_SIZE);
+
+ return 0;
+}
+
+WORD
+mpio_dentry_get_startsector(mpio_t *m, BYTE *p)
+{
+ int s;
+ int sektor;
+ mpio_dir_slot_t *dentry;
+
+ s = mpio_dentry_get_size(m, p);
+ s -= DIR_ENTRY_SIZE ;
+
+ dentry = (mpio_dir_slot_t *)p;
+
+ while (s != 0) {
+ dentry++;
+ s -= DIR_ENTRY_SIZE ;
+ }
+
+ sektor = dentry->start[1] * 0x100 + dentry->start[0];
+
+ return sektor;
+}
+
+int
+mpio_dentry_put(mpio_t *m, BYTE mem,
+ BYTE *filename, int filename_size,
+ WORD year, BYTE month, BYTE day,
+ BYTE hour, BYTE minute, DWORD fsize, WORD ssector)
+{
+ BYTE *unicode = 0;
+ BYTE *back, *fback;
+ BYTE *fname = 0;
+ iconv_t ic;
+ int in = 0, out = 0;
+ int fin = 0, fout = 0;
+ int count = 0;
+ BYTE index;
+
+ BYTE *p;
+ mpio_dir_entry_t *dentry;
+ mpio_dir_slot_t *slot;
+
+ p = mpio_directory_open(m, mem);
+ if (p) {
+ while (*p != 0x00)
+ p += 0x20;
+ } else {
+ if (mem == MPIO_EXTERNAL_MEM)
+ p = m->external.dir;
+ if (mem == MPIO_INTERNAL_MEM)
+ p = m->internal.dir;
+ }
+
+ /* generate vfat filename in UNICODE */
+ ic = iconv_open("UNICODE", "ASCII");
+ fin = in = filename_size + 1;
+ fout = out = filename_size * 2 + 2 + 26;
+ fname = malloc(in);
+ fback = fname;
+ unicode = malloc(out);
+ back = unicode;
+
+ memset(fname, 0, in);
+ snprintf(fname, in, "%s", filename);
+ memset(unicode, 0xff, out);
+ iconv(ic, (char **)&fback, &fin, (char **)&back, &fout);
+ iconv_close(ic);
+ hexdump(fname, in);
+ hexdump(unicode, out);
+
+ back = unicode + 2;
+
+ count = filename_size / 13;
+ if (filename_size % 13)
+ count++;
+
+ slot = (mpio_dir_slot_t *)p;
+
+ index = 0x40 + count;
+ while (count > 0) {
+ mpio_dentry_copy_to_slot(back + ((count - 1) * 26), slot);
+ hexdump((char *)back + ((count - 1) * 26), 0x20);
+ slot->id = index;
+ slot->attr = 0x0f;
+ slot->reserved = 0x00;
+ slot->start[0] = 0x00;
+ slot->start[1] = 0x00;
+ /* FIXME: */
+ slot->alias_checksum = 0x00; // checksum for 8.3 alias
+
+ hexdump((char *)slot, 0x20);
+
+ slot++;
+ count--;
+ index = count;
+ }
+
+/* memcpy(p, m->internal.dir+0x220, 0x20); */
+
+/* p+=0x20; */
+ dentry = (mpio_dir_entry_t *)slot;
+ memcpy(dentry->name,"AAAAAAAA",8);
+ memcpy(dentry->ext,"MP3",3);
+ dentry->attr = 0x20;
+ dentry->lcase = 0x00;
+ dentry->ctime_ms = 0x00;
+ dentry->ctime[0] = 0x37;
+ dentry->ctime[1] = 0x7b;
+ dentry->cdate[0] = 0xfb;
+ dentry->cdate[1] = 0x2c;
+ dentry->adate[0] = 0xfd;
+ dentry->adate[1] = 0x2c;
+ dentry->reserved[0] = 0x00;
+ dentry->reserved[1] = 0x00;
+ dentry->time[0] = 0x38;
+ dentry->time[1] = 0x7b;
+ dentry->date[0] = 0xfb;
+ dentry->date[1] = 0x2c;
+ dentry->size[0] = fsize & 0xff;
+ dentry->size[1] = (fsize / 0x100) & 0xff;
+ dentry->size[2] = (fsize / 0x10000) & 0xff;
+ dentry->size[3] = (fsize / 0x1000000) & 0xff;
+ dentry->start[0] = ssector & 0xff;
+ dentry->start[1] = ssector / 0x100;
+
+ free(unicode);
+ free(fname);
+
+ /* what do we want to return? */
+ return 0;
+}
+
+BYTE *
+mpio_dentry_find_name_8_3(mpio_t *m, BYTE mem, BYTE *filename)
+{
+ BYTE *p;
+ BYTE bdummy;
+ WORD wdummy;
+ BYTE fname[129];
+ BYTE fname_8_3[13];
+ DWORD ddummy;
+ BYTE *found = 0;
+
+ p = mpio_directory_open(m, mem);
+ while ((p) && (!found)) {
+ mpio_dentry_get_real (m, p,
+ fname, 128,
+ fname_8_3,
+ &wdummy, &bdummy, &bdummy,
+ &bdummy, &bdummy, &ddummy);
+ if ((strcmp(fname_8_3, filename) == 0) &&
+ (strcmp(filename,fname_8_3) == 0)) {
+ found = p;
+ p = NULL;
+ }
+
+ p = mpio_dentry_next(m, p);
+ }
+
+ return found;
+}
+
+BYTE *
+mpio_dentry_find_name(mpio_t *m, BYTE mem, BYTE *filename)
+{
+ BYTE *p;
+ BYTE bdummy;
+ WORD wdummy;
+ BYTE fname[129];
+ DWORD ddummy;
+ BYTE *found = 0;
+
+ p = mpio_directory_open(m, mem);
+ while ((p) && (!found)) {
+ mpio_dentry_get (m, p,
+ fname, 128,
+ &wdummy, &bdummy, &bdummy,
+ &bdummy, &bdummy, &ddummy);
+ if ((strcmp(fname,filename) == 0) && (strcmp(filename,fname) == 0)) {
+ found = p;
+ p = NULL;
+ }
+
+ p = mpio_dentry_next(m, p);
+ }
+
+ return found;
+}
+
+
+int
+mpio_dentry_delete(mpio_t *m, BYTE mem, BYTE *filename)
+{
+ mpio_smartmedia_t *sm;
+ BYTE *start;
+ int size;
+ BYTE tmp[DIR_SIZE];
+
+ if (mem == MPIO_INTERNAL_MEM) sm = &m->internal;
+ if (mem==MPIO_EXTERNAL_MEM) sm = &m->external;
+
+ start = mpio_dentry_find_name(m, mem, filename);
+
+ /* second try */
+ if (!start)
+ start = mpio_dentry_find_name_8_3(m, mem, filename);
+
+ if (!start) {
+ debug("could not find file: %s\n", filename);
+ return 0;
+ }
+
+ size = mpio_dentry_get_size(m, start);
+
+ if (size <= 0) {
+ debug("fatal error in mpio_dentry_delete\n");
+ return 0;
+ }
+
+ debugn(5, "size: %2x\n", size);
+
+ /* clear new buffer */
+ memset(tmp, 0, DIR_SIZE);
+ /* copy before delete */
+ if (start != sm->dir)
+ memcpy(tmp, sm->dir, (start - (sm->dir)));
+ /* copy after delete */
+ memcpy(tmp + (start - (sm->dir)), (start + size),
+ (sm->dir + DIR_SIZE - (start + size)));
+
+ memcpy(sm->dir, tmp, DIR_SIZE);
+
+ return 0;
+}