Make database endianess independent.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@12297 a1c6a512-1295-4272-9138-f99709370657
This commit is contained in:
parent
24c8da0b56
commit
9b9539c8d3
6 changed files with 288 additions and 51 deletions
124
apps/tagcache.c
124
apps/tagcache.c
|
@ -69,6 +69,7 @@
|
|||
#include "misc.h"
|
||||
#include "settings.h"
|
||||
#include "dircache.h"
|
||||
#include "structec.h"
|
||||
#ifndef __PCTOOL__
|
||||
#include "atoi.h"
|
||||
#include "splash.h"
|
||||
|
@ -159,6 +160,12 @@ struct master_header {
|
|||
long serial; /* Increasing counting number */
|
||||
};
|
||||
|
||||
/* For the endianess correction */
|
||||
static const char *tagfile_entry_ec = "ss";
|
||||
static const char *index_entry_ec = "llllllllllllllll"; /* (1 + TAG_COUNT) * l */
|
||||
static const char *tagcache_header_ec = "lll";
|
||||
static const char *master_header_ec = "llll";
|
||||
|
||||
static long current_serial;
|
||||
|
||||
#ifdef HAVE_TC_RAMCACHE
|
||||
|
@ -296,7 +303,7 @@ static int open_tag_fd(struct tagcache_header *hdr, int tag, bool write)
|
|||
}
|
||||
|
||||
/* Check the header. */
|
||||
rc = read(fd, hdr, sizeof(struct tagcache_header));
|
||||
rc = ecread(fd, hdr, 1, tagcache_header_ec, tc_stat.econ);
|
||||
if (hdr->magic != TAGCACHE_MAGIC || rc != sizeof(struct tagcache_header))
|
||||
{
|
||||
logf("header error");
|
||||
|
@ -399,8 +406,8 @@ static long find_entry_disk(const char *filename)
|
|||
pos_history[i+1] = pos_history[i];
|
||||
pos_history[0] = pos;
|
||||
|
||||
if (read(fd, &tfe, sizeof(struct tagfile_entry)) !=
|
||||
sizeof(struct tagfile_entry))
|
||||
if (ecread(fd, &tfe, 1, tagfile_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct tagfile_entry))
|
||||
{
|
||||
break ;
|
||||
}
|
||||
|
@ -512,8 +519,8 @@ static bool get_index(int masterfd, int idxid,
|
|||
|
||||
lseek(masterfd, idxid * sizeof(struct index_entry)
|
||||
+ sizeof(struct master_header), SEEK_SET);
|
||||
if (read(masterfd, idx, sizeof(struct index_entry)) !=
|
||||
sizeof(struct index_entry))
|
||||
if (ecread(masterfd, idx, 1, index_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct index_entry))
|
||||
{
|
||||
logf("read error #3");
|
||||
return false;
|
||||
|
@ -543,8 +550,8 @@ static bool write_index(int masterfd, int idxid, struct index_entry *idx)
|
|||
|
||||
lseek(masterfd, idxid * sizeof(struct index_entry)
|
||||
+ sizeof(struct master_header), SEEK_SET);
|
||||
if (write(masterfd, idx, sizeof(struct index_entry)) !=
|
||||
sizeof(struct index_entry))
|
||||
if (ecwrite(masterfd, idx, 1, index_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct index_entry))
|
||||
{
|
||||
logf("write error #3");
|
||||
logf("idxid: %d", idxid);
|
||||
|
@ -619,8 +626,8 @@ static bool retrieve(struct tagcache_search *tcs, struct index_entry *idx,
|
|||
return false;
|
||||
|
||||
lseek(tcs->idxfd[tag], seek, SEEK_SET);
|
||||
if (read(tcs->idxfd[tag], &tfe, sizeof(struct tagfile_entry)) !=
|
||||
sizeof(struct tagfile_entry))
|
||||
if (ecread(tcs->idxfd[tag], &tfe, 1, tagfile_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct tagfile_entry))
|
||||
{
|
||||
logf("read error #5");
|
||||
return false;
|
||||
|
@ -831,7 +838,7 @@ static bool check_clauses(struct tagcache_search *tcs,
|
|||
{
|
||||
int fd = tcs->idxfd[clause[i]->tag];
|
||||
lseek(fd, seek, SEEK_SET);
|
||||
read(fd, &tfe, sizeof(struct tagfile_entry));
|
||||
ecread(fd, &tfe, 1, tagfile_entry_ec, tc_stat.econ);
|
||||
if (tfe.tag_length >= (int)sizeof(str))
|
||||
{
|
||||
logf("Too long tag read!");
|
||||
|
@ -952,8 +959,8 @@ static bool build_lookup_list(struct tagcache_search *tcs)
|
|||
lseek(tcs->masterfd, tcs->seek_pos * sizeof(struct index_entry) +
|
||||
sizeof(struct master_header), SEEK_SET);
|
||||
|
||||
while (read(tcs->masterfd, &entry, sizeof(struct index_entry)) ==
|
||||
sizeof(struct index_entry))
|
||||
while (ecread(tcs->masterfd, &entry, 1, index_entry_ec, tc_stat.econ)
|
||||
== sizeof(struct index_entry))
|
||||
{
|
||||
/* Check if entry has been deleted. */
|
||||
if (entry.flag & FLAG_DELETED)
|
||||
|
@ -1001,6 +1008,7 @@ static void remove_files(void)
|
|||
|
||||
tc_stat.ready = false;
|
||||
tc_stat.ramcache = false;
|
||||
tc_stat.econ = false;
|
||||
remove(TAGCACHE_FILE_MASTER);
|
||||
for (i = 0; i < TAG_COUNT; i++)
|
||||
{
|
||||
|
@ -1026,8 +1034,20 @@ static int open_master_fd(struct master_header *hdr, bool write)
|
|||
return fd;
|
||||
}
|
||||
|
||||
tc_stat.econ = false;
|
||||
|
||||
/* Check the header. */
|
||||
rc = read(fd, hdr, sizeof(struct master_header));
|
||||
if (hdr->tch.magic == TAGCACHE_MAGIC && rc == sizeof(struct master_header))
|
||||
{
|
||||
/* Success. */
|
||||
return fd;
|
||||
}
|
||||
|
||||
/* Trying to read again, this time with endianess correction enabled. */
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
rc = ecread(fd, hdr, 1, master_header_ec, true);
|
||||
if (hdr->tch.magic != TAGCACHE_MAGIC || rc != sizeof(struct master_header))
|
||||
{
|
||||
logf("header error");
|
||||
|
@ -1035,6 +1055,8 @@ static int open_master_fd(struct master_header *hdr, bool write)
|
|||
close(fd);
|
||||
return -2;
|
||||
}
|
||||
|
||||
tc_stat.econ = true;
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
@ -1260,8 +1282,8 @@ static bool get_next(struct tagcache_search *tcs)
|
|||
return false;
|
||||
|
||||
tcs->result_seek = lseek(tcs->idxfd[tcs->type], 0, SEEK_CUR);
|
||||
if (read(tcs->idxfd[tcs->type], &entry, sizeof(struct tagfile_entry)) !=
|
||||
sizeof(struct tagfile_entry))
|
||||
if (ecread(tcs->idxfd[tcs->type], &entry, 1,
|
||||
tagfile_entry_ec, tc_stat.econ) != sizeof(struct tagfile_entry))
|
||||
{
|
||||
/* End of data. */
|
||||
tcs->valid = false;
|
||||
|
@ -1739,7 +1761,7 @@ static int tempbuf_sort(int fd)
|
|||
}
|
||||
#endif
|
||||
|
||||
if (write(fd, &fe, sizeof(struct tagfile_entry)) !=
|
||||
if (ecwrite(fd, &fe, 1, tagfile_entry_ec, tc_stat.econ) !=
|
||||
sizeof(struct tagfile_entry))
|
||||
{
|
||||
logf("tempbuf_sort: write error #1");
|
||||
|
@ -1833,8 +1855,8 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
|
|||
{
|
||||
int loc = lseek(masterfd, 0, SEEK_CUR);
|
||||
|
||||
if (read(masterfd, &idx, sizeof(struct index_entry)) !=
|
||||
sizeof(struct index_entry))
|
||||
if (ecread(masterfd, &idx, 1, index_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct index_entry))
|
||||
{
|
||||
logf("read fail #2");
|
||||
close(masterfd);
|
||||
|
@ -1852,8 +1874,8 @@ static bool build_numeric_indices(struct tagcache_header *h, int tmpfd)
|
|||
|
||||
/* Write back the updated index. */
|
||||
lseek(masterfd, loc, SEEK_SET);
|
||||
if (write(masterfd, &idx, sizeof(struct index_entry)) !=
|
||||
sizeof(struct index_entry))
|
||||
if (ecwrite(masterfd, &idx, 1, index_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct index_entry))
|
||||
{
|
||||
logf("write fail");
|
||||
close(masterfd);
|
||||
|
@ -1977,7 +1999,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
int loc = lseek(fd, 0, SEEK_CUR);
|
||||
bool ret;
|
||||
|
||||
if (read(fd, &entry, sizeof(struct tagfile_entry))
|
||||
if (ecread(fd, &entry, 1, tagfile_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct tagfile_entry))
|
||||
{
|
||||
logf("read error #7");
|
||||
|
@ -2041,8 +2063,8 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
tch.entry_count = 0;
|
||||
tch.datasize = 0;
|
||||
|
||||
if (write(fd, &tch, sizeof(struct tagcache_header)) !=
|
||||
sizeof(struct tagcache_header))
|
||||
if (ecwrite(fd, &tch, 1, tagcache_header_ec, tc_stat.econ)
|
||||
!= sizeof(struct tagcache_header))
|
||||
{
|
||||
logf("header write failed");
|
||||
close(fd);
|
||||
|
@ -2071,7 +2093,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
tcmh.tch = *h;
|
||||
tcmh.tch.entry_count = 0;
|
||||
tcmh.tch.datasize = 0;
|
||||
write(masterfd, &tcmh, sizeof(struct master_header));
|
||||
ecwrite(masterfd, &tcmh, 1, master_header_ec, tc_stat.econ);
|
||||
init = true;
|
||||
masterfd_pos = lseek(masterfd, 0, SEEK_CUR);
|
||||
current_serial = 0;
|
||||
|
@ -2084,7 +2106,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
*/
|
||||
init = false;
|
||||
|
||||
if (read(masterfd, &tcmh, sizeof(struct master_header)) !=
|
||||
if (ecread(masterfd, &tcmh, 1, master_header_ec, tc_stat.econ) !=
|
||||
sizeof(struct master_header) || tcmh.tch.magic != TAGCACHE_MAGIC)
|
||||
{
|
||||
logf("header error");
|
||||
|
@ -2125,7 +2147,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) !=
|
||||
sizeof(struct temp_file_entry))
|
||||
{
|
||||
logf("read fail #1");
|
||||
logf("read fail #3");
|
||||
error = true;
|
||||
goto error_exit;
|
||||
}
|
||||
|
@ -2142,7 +2164,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
if (read(tmpfd, buf, entry.tag_length[index_type]) !=
|
||||
entry.tag_length[index_type])
|
||||
{
|
||||
logf("read fail #3");
|
||||
logf("read fail #4");
|
||||
error = true;
|
||||
goto error_exit;
|
||||
}
|
||||
|
@ -2184,10 +2206,10 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
|
||||
idxbuf_pos = MIN(tcmh.tch.entry_count - i, IDX_BUF_DEPTH);
|
||||
|
||||
if (read(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
|
||||
(int)sizeof(struct index_entry)*idxbuf_pos)
|
||||
if (ecread(masterfd, idxbuf, idxbuf_pos, index_entry_ec, tc_stat.econ)
|
||||
!= (int)sizeof(struct index_entry)*idxbuf_pos)
|
||||
{
|
||||
logf("read fail #2");
|
||||
logf("read fail #5");
|
||||
error = true;
|
||||
goto error_exit ;
|
||||
}
|
||||
|
@ -2217,7 +2239,8 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
}
|
||||
|
||||
/* Write back the updated index. */
|
||||
if (write(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
|
||||
if (ecwrite(masterfd, idxbuf, idxbuf_pos,
|
||||
index_entry_ec, tc_stat.econ) !=
|
||||
(int)sizeof(struct index_entry)*idxbuf_pos)
|
||||
{
|
||||
logf("write fail");
|
||||
|
@ -2249,10 +2272,10 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
{
|
||||
int loc = lseek(masterfd, 0, SEEK_CUR);
|
||||
|
||||
if (read(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
|
||||
(int)sizeof(struct index_entry)*idxbuf_pos)
|
||||
if (ecread(masterfd, idxbuf, idxbuf_pos, index_entry_ec, tc_stat.econ)
|
||||
!= (int)sizeof(struct index_entry)*idxbuf_pos)
|
||||
{
|
||||
logf("read fail #2");
|
||||
logf("read fail #6");
|
||||
error = true;
|
||||
break ;
|
||||
}
|
||||
|
@ -2270,7 +2293,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
if (read(tmpfd, &entry, sizeof(struct temp_file_entry)) !=
|
||||
sizeof(struct temp_file_entry))
|
||||
{
|
||||
logf("read fail #1");
|
||||
logf("read fail #7");
|
||||
error = true;
|
||||
break ;
|
||||
}
|
||||
|
@ -2289,7 +2312,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
if (read(tmpfd, buf, entry.tag_length[index_type]) !=
|
||||
entry.tag_length[index_type])
|
||||
{
|
||||
logf("read fail #3");
|
||||
logf("read fail #8");
|
||||
logf("offset=0x%02x", entry.tag_offset[index_type]);
|
||||
logf("length=0x%02x", entry.tag_length[index_type]);
|
||||
error = true;
|
||||
|
@ -2300,7 +2323,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
idxbuf[j].tag_seek[index_type] = lseek(fd, 0, SEEK_CUR);
|
||||
fe.tag_length = entry.tag_length[index_type];
|
||||
fe.idx_id = tcmh.tch.entry_count + i + j;
|
||||
write(fd, &fe, sizeof(struct tagfile_entry));
|
||||
ecwrite(fd, &fe, 1, tagfile_entry_ec, tc_stat.econ);
|
||||
write(fd, buf, fe.tag_length);
|
||||
tempbufidx++;
|
||||
|
||||
|
@ -2322,7 +2345,8 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
}
|
||||
|
||||
/* Write index. */
|
||||
if (write(masterfd, idxbuf, sizeof(struct index_entry)*idxbuf_pos) !=
|
||||
if (ecwrite(masterfd, idxbuf, idxbuf_pos,
|
||||
index_entry_ec, tc_stat.econ) !=
|
||||
(int)sizeof(struct index_entry)*idxbuf_pos)
|
||||
{
|
||||
logf("tagcache: write fail #4");
|
||||
|
@ -2339,7 +2363,7 @@ static int build_index(int index_type, struct tagcache_header *h, int tmpfd)
|
|||
tch.entry_count = tempbufidx;
|
||||
tch.datasize = lseek(fd, 0, SEEK_END) - sizeof(struct tagcache_header);
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, &tch, sizeof(struct tagcache_header));
|
||||
ecwrite(fd, &tch, 1, tagcache_header_ec, tc_stat.econ);
|
||||
|
||||
if (index_type != tag_filename)
|
||||
h->datasize += tch.datasize;
|
||||
|
@ -2495,7 +2519,7 @@ static bool commit(void)
|
|||
+ tch.datasize;
|
||||
|
||||
lseek(masterfd, 0, SEEK_SET);
|
||||
write(masterfd, &tcmh, sizeof(struct master_header));
|
||||
ecwrite(masterfd, &tcmh, 1, master_header_ec, tc_stat.econ);
|
||||
close(masterfd);
|
||||
|
||||
logf("tagcache committed");
|
||||
|
@ -2570,7 +2594,7 @@ static bool update_current_serial(long serial)
|
|||
|
||||
/* Write it back */
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
write(fd, &myhdr, sizeof(struct master_header));
|
||||
ecwrite(fd, &myhdr, 1, master_header_ec, tc_stat.econ);
|
||||
close(fd);
|
||||
|
||||
return true;
|
||||
|
@ -2872,14 +2896,14 @@ bool tagcache_create_changelog(struct tagcache_search *tcs)
|
|||
else
|
||||
{
|
||||
lseek(tcs->masterfd, 0, SEEK_SET);
|
||||
read(tcs->masterfd, &myhdr, sizeof(struct master_header));
|
||||
ecread(tcs->masterfd, &myhdr, 1, master_header_ec, tc_stat.econ);
|
||||
}
|
||||
|
||||
write(clfd, "## Changelog version 1\n", 23);
|
||||
|
||||
for (i = 0; i < myhdr.tch.entry_count; i++)
|
||||
{
|
||||
if (read(tcs->masterfd, &idx, sizeof(struct index_entry))
|
||||
if (ecread(tcs->masterfd, &idx, 1, index_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct index_entry))
|
||||
{
|
||||
logf("read error #9");
|
||||
|
@ -2943,7 +2967,7 @@ static bool delete_entry(long idx_id)
|
|||
return false;
|
||||
|
||||
lseek(fd, idx_id * sizeof(struct index_entry), SEEK_CUR);
|
||||
if (read(fd, &myidx, sizeof(struct index_entry))
|
||||
if (ecread(fd, &myidx, 1, index_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct index_entry))
|
||||
{
|
||||
logf("delete_entry(): read error");
|
||||
|
@ -2953,7 +2977,7 @@ static bool delete_entry(long idx_id)
|
|||
|
||||
myidx.flag |= FLAG_DELETED;
|
||||
lseek(fd, -sizeof(struct index_entry), SEEK_CUR);
|
||||
if (write(fd, &myidx, sizeof(struct index_entry))
|
||||
if (ecwrite(fd, &myidx, 1, index_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct index_entry))
|
||||
{
|
||||
logf("delete_entry(): write_error");
|
||||
|
@ -2968,7 +2992,7 @@ static bool delete_entry(long idx_id)
|
|||
lseek(fd, sizeof(struct master_header), SEEK_SET);
|
||||
for (i = 0; i < myhdr.tch.entry_count; i++)
|
||||
{
|
||||
if (read(fd, &idx, sizeof(struct index_entry))
|
||||
if (ecread(fd, &idx, 1, index_entry_ec, tc_stat.econ)
|
||||
!= sizeof(struct index_entry))
|
||||
{
|
||||
logf("delete_entry(): read error #2");
|
||||
|
@ -3190,7 +3214,7 @@ static bool load_tagcache(void)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (read(fd, &hdr->h, sizeof(struct master_header))
|
||||
if (ecread(fd, &hdr->h, 1, master_header_ec, tc_stat.econ)
|
||||
!= sizeof(struct master_header)
|
||||
|| hdr->h.tch.magic != TAGCACHE_MAGIC)
|
||||
{
|
||||
|
@ -3203,7 +3227,7 @@ static bool load_tagcache(void)
|
|||
/* Load the master index table. */
|
||||
for (i = 0; i < hdr->h.tch.entry_count; i++)
|
||||
{
|
||||
rc = read(fd, idx, sizeof(struct index_entry));
|
||||
rc = ecread(fd, idx, 1, index_entry_ec, tc_stat.econ);
|
||||
if (rc != sizeof(struct index_entry))
|
||||
{
|
||||
logf("read error #10");
|
||||
|
@ -3262,7 +3286,7 @@ static bool load_tagcache(void)
|
|||
|
||||
fe = (struct tagfile_entry *)p;
|
||||
pos = lseek(fd, 0, SEEK_CUR);
|
||||
rc = read(fd, fe, sizeof(struct tagfile_entry));
|
||||
rc = ecread(fd, fe, 1, tagfile_entry_ec, tc_stat.econ);
|
||||
if (rc != sizeof(struct tagfile_entry))
|
||||
{
|
||||
/* End of lookup table. */
|
||||
|
@ -3413,7 +3437,7 @@ static bool check_deleted_files(void)
|
|||
}
|
||||
|
||||
lseek(fd, sizeof(struct tagcache_header), SEEK_SET);
|
||||
while (read(fd, &tfe, sizeof(struct tagfile_entry))
|
||||
while (ecread(fd, &tfe, 1, tagfile_entry_ec, tc_stat.econ)
|
||||
== sizeof(struct tagfile_entry)
|
||||
#ifndef __PCTOOL__
|
||||
&& !check_event_queue()
|
||||
|
@ -3443,7 +3467,7 @@ static bool check_deleted_files(void)
|
|||
if (testfd < 0)
|
||||
{
|
||||
logf("Entry no longer valid.");
|
||||
logf("-> %s", buf);
|
||||
logf("-> %s / %d", buf, tfe.tag_length);
|
||||
delete_entry(tfe.idx_id);
|
||||
}
|
||||
close(testfd);
|
||||
|
|
|
@ -88,6 +88,7 @@ struct tagcache_stat {
|
|||
bool ready; /* Is tagcache ready to be used? */
|
||||
bool ramcache; /* Is tagcache loaded in ram? */
|
||||
bool commit_delayed; /* Has commit been delayed until next reboot? */
|
||||
bool econ; /* Is endianess correction enabled? */
|
||||
int commit_step; /* Commit progress */
|
||||
int ramcache_allocated; /* Has ram been allocated for ramcache? */
|
||||
int ramcache_used; /* How much ram has been really used */
|
||||
|
|
|
@ -53,6 +53,7 @@ common/strncmp.c
|
|||
common/strncpy.c
|
||||
common/strrchr.c
|
||||
common/strtok.c
|
||||
common/structec.c
|
||||
common/timefuncs.c
|
||||
common/unicode.c
|
||||
|
||||
|
|
179
firmware/common/structec.c
Normal file
179
firmware/common/structec.c
Normal file
|
@ -0,0 +1,179 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2007 by Miika Pekkarinen
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#include <string.h>
|
||||
#include "structec.h"
|
||||
#include "system.h"
|
||||
#include "file.h"
|
||||
|
||||
#define MAX_STRUCT_SIZE 128
|
||||
|
||||
/**
|
||||
* Convert the struct endianess with the instructions provided.
|
||||
*
|
||||
* For example:
|
||||
* struct test {
|
||||
* long par1;
|
||||
* short par2;
|
||||
* short par3;
|
||||
* };
|
||||
*
|
||||
* structec_convert(instance_of_test, "lss", sizeof(struct test), true);
|
||||
*
|
||||
* Structures to be converted must be properly padded.
|
||||
*
|
||||
* @param structure Pointer to the struct being converted.
|
||||
* @param ecinst Instructions how to do the endianess conversion.
|
||||
* @param count Number of structures to write
|
||||
* @param enable Conversion is not made unless this is true.
|
||||
*/
|
||||
void structec_convert(void *structure, const char *ecinst,
|
||||
long count, bool enable)
|
||||
{
|
||||
const char *ecinst_ring = ecinst;
|
||||
char *buf = (char *)structure;
|
||||
|
||||
if (!enable)
|
||||
return;
|
||||
|
||||
while (count > 0)
|
||||
{
|
||||
switch (*ecinst_ring)
|
||||
{
|
||||
/* Swap nothing. */
|
||||
case 'c':
|
||||
{
|
||||
buf++;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Swap 2 bytes. */
|
||||
case 's':
|
||||
{
|
||||
unsigned short *data = (unsigned short *)buf;
|
||||
*data = SWAP_16(*data);
|
||||
buf += 2;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Swap 4 bytes. */
|
||||
case 'l':
|
||||
{
|
||||
unsigned long *data = (unsigned long *)buf;
|
||||
*data = SWAP_32(*data);
|
||||
buf += 4;
|
||||
break;
|
||||
}
|
||||
|
||||
/* This should be never reached. */
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
ecinst_ring++;
|
||||
if (*ecinst_ring == '\0')
|
||||
{
|
||||
ecinst_ring = ecinst;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the size of a struct in bytes by using endianess correction
|
||||
* string format.
|
||||
*
|
||||
* @param ecinst endianess correction string.
|
||||
* @return length of the struct in bytes.
|
||||
*/
|
||||
size_t structec_size(const char *ecinst)
|
||||
{
|
||||
size_t size = 0;
|
||||
|
||||
do
|
||||
{
|
||||
switch (*ecinst)
|
||||
{
|
||||
case 'c': size += 1; break;
|
||||
case 's': size += 2; break;
|
||||
case 'l': size += 4; break;
|
||||
default: break;
|
||||
}
|
||||
} while (*(++ecinst) != '\0');
|
||||
|
||||
return size;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads endianess corrected structure members from the given file.
|
||||
*
|
||||
* @param fd file descriptor of the file being read.
|
||||
* @param buf endianess corrected data is placed here.
|
||||
* @param scount the number of struct members to read.
|
||||
* @param ecinst endianess correction string.
|
||||
* @param ec if true, endianess correction is enabled.
|
||||
*/
|
||||
ssize_t ecread(int fd, void *buf, size_t scount, const char *ecinst, bool ec)
|
||||
{
|
||||
ssize_t ret;
|
||||
size_t member_size = structec_size(ecinst);
|
||||
|
||||
ret = read(fd, buf, scount * member_size);
|
||||
structec_convert(buf, ecinst, scount, ec);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes endianess corrected structure members to the given file.
|
||||
*
|
||||
* @param fd file descriptor of the file being written to.
|
||||
* @param buf endianess corrected data is read here.
|
||||
* @param scount the number of struct members to write.
|
||||
* @param ecinst endianess correction string.
|
||||
* @param ec if true, endianess correction is enabled.
|
||||
*/
|
||||
ssize_t ecwrite(int fd, const void *buf, size_t scount,
|
||||
const char *ecinst, bool ec)
|
||||
{
|
||||
char tmp[MAX_STRUCT_SIZE];
|
||||
size_t member_size = structec_size(ecinst);
|
||||
|
||||
if (ec)
|
||||
{
|
||||
const char *p = (const char *)buf;
|
||||
int maxamount = (int)(MAX_STRUCT_SIZE / member_size);
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (long)scount; i += maxamount)
|
||||
{
|
||||
long amount = MIN((int)scount-i, maxamount);
|
||||
|
||||
memcpy(tmp, p, member_size * amount);
|
||||
structec_convert(tmp, ecinst, amount, true);
|
||||
write(fd, tmp, amount * member_size);
|
||||
p += member_size * amount;
|
||||
}
|
||||
|
||||
return scount * member_size;
|
||||
}
|
||||
|
||||
return write(fd, buf, scount * member_size);
|
||||
}
|
||||
|
31
firmware/export/structec.h
Normal file
31
firmware/export/structec.h
Normal file
|
@ -0,0 +1,31 @@
|
|||
/***************************************************************************
|
||||
* __________ __ ___.
|
||||
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
|
||||
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
|
||||
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
|
||||
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
|
||||
* \/ \/ \/ \/ \/
|
||||
* $Id$
|
||||
*
|
||||
* Copyright (C) 2007 by Miika Pekkarinen
|
||||
*
|
||||
* All files in this archive are subject to the GNU General Public License.
|
||||
* See the file COPYING in the source tree root for full license agreement.
|
||||
*
|
||||
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
|
||||
* KIND, either express or implied.
|
||||
*
|
||||
****************************************************************************/
|
||||
|
||||
#ifndef _STRUCTEC_H
|
||||
#define _STRUCTEC_H
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
void structec_convert(void *structure, const char *ecinst,
|
||||
long count, bool enable);
|
||||
ssize_t ecread(int fd, void *buf, size_t scount, const char *ecinst, bool ec);
|
||||
ssize_t ecwrite(int fd, const void *buf, size_t scount, const char *ecinst, bool ec);
|
||||
#endif
|
||||
|
|
@ -41,7 +41,8 @@ ipod_fw: ipod_fw.c
|
|||
database: database.c ../apps/tagcache.c ../apps/metadata.c \
|
||||
../firmware/id3.c ../firmware/common/unicode.c \
|
||||
../firmware/common/crc32.c ../uisimulator/common/io.c \
|
||||
../firmware/mp3data.c ../firmware/logf.c ../firmware/replaygain.c
|
||||
../firmware/mp3data.c ../firmware/logf.c ../firmware/replaygain.c \
|
||||
../firmware/common/structec.c
|
||||
$(SILENT)$(CC) -g -I../firmware/export -iquote ../firmware/include \
|
||||
-D__PCTOOL__ -DHAVE_TAGCACHE -DROCKBOX_HAS_LOGF -DSIMULATOR \
|
||||
-DCONFIG_CODEC=1 -ldl -I../apps $+ -o $@
|
||||
|
|
Loading…
Reference in a new issue