summaryrefslogtreecommitdiff
path: root/packedstorage.c
diff options
context:
space:
mode:
Diffstat (limited to 'packedstorage.c')
-rw-r--r--packedstorage.c131
1 files changed, 131 insertions, 0 deletions
diff --git a/packedstorage.c b/packedstorage.c
new file mode 100644
index 0000000..f23866f
--- /dev/null
+++ b/packedstorage.c
@@ -0,0 +1,131 @@
+/*************************************************************** -*- c++ -*-
+ * Copyright (c) 2003,2004 by Marcel Wiesweg *
+ * *
+ * 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. *
+ * *
+ ***************************************************************************/
+
+#include "packedstorage.h"
+
+PackedStorage::PackedStorage(int maxMB)
+ : LegacyStorage(maxMB) {
+}
+#define TOC_SIZE 8
+//The file structure is simple:
+// TOC_SIZE*PageAddress contains the numbers of the following pages
+// TOC_SIZE*TELETEXT_PAGESIZE contains the page data
+//and the same again.
+bool PackedStorage::seekTo(PageID page, int desc, bool create) {
+ lseek(desc, 0, SEEK_SET);
+ PageAddress addr[TOC_SIZE];
+
+ while (::read(desc, addr, sizeof(addr)) == sizeof(addr)) {
+ lseek(desc, 0, SEEK_CUR);
+ for (int index=0; index<TOC_SIZE; index++) {
+ if (addr[index]==page) {
+ lseek(desc, index*TELETEXT_PAGESIZE, SEEK_CUR);
+ return true;
+ } else if (addr[index].page==0) {
+ //0 means: no more pages follow
+ if (create) {
+ //rewind what was read
+ lseek(desc, -(off_t)sizeof(addr), SEEK_CUR);
+ //update index
+ addr[index]=page;
+ if (::write(desc, addr, sizeof(addr)) != sizeof(addr))
+ return false;
+ //seek to data position
+ lseek(desc, TELETEXT_PAGESIZE*index, SEEK_CUR);
+ return true;
+ } else
+ return false;
+ }
+ }
+
+ //seek over data area
+ lseek(desc, TELETEXT_PAGESIZE*TOC_SIZE, SEEK_CUR);
+ }
+
+ int oldSize=actualFileSize(lseek(desc, 0, SEEK_CUR));
+ if (create) {
+ //create a new set of a TOC and a TOC_SIZE*TELETEXT_PAGESIZE data area
+ memset(addr, 0, sizeof(addr));
+ //first entry is our page
+ addr[0]=page;
+ if (::write(desc, addr, sizeof(addr)) != sizeof(addr))
+ return false;
+ //seek beyond end of file
+ lseek(desc, (TELETEXT_PAGESIZE*TOC_SIZE)-1, SEEK_CUR);
+ //write one byte to enlarge the file to the sought position
+ char c=1;
+ if (::write(desc, &c, 1) != 1)
+ return false;
+ //Now, calculate new file size
+ byteCount += ( actualFileSize(lseek(desc, 0, SEEK_CUR)) - oldSize );
+ //seek to beginning of data, which is requested
+ lseek(desc, -(off_t)(TELETEXT_PAGESIZE*TOC_SIZE), SEEK_CUR);
+ return true;
+ } else
+ return false;
+}
+
+void PackedStorage::getFilename(char *buffer, int bufLength, PageID page) {
+ //This is a different scheme: page 576_07 will have the name 570s.vtx, the same as e.g. 571_01 or 575_00
+ //Think of "the five hundred seventies"
+ snprintf(buffer, bufLength, "%s/%s/%03xs.vtx", getRootDir(),
+ *page.channel.ToString(), (page.page & 0xFF0));
+}
+
+StorageHandle PackedStorage::openForWriting(PageID page) {
+ static bool wroteError=false;
+ char filename[PATH_MAX];
+ getFilename(filename, sizeof(filename), page);
+ //first try
+ int desc=open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (desc != -1) {
+ if (!seekTo(page, desc, true)) {
+ ::close(desc);
+ return StorageHandle();
+ }
+ if ( maxBytes && byteCount>maxBytes )
+ freeSpace();
+ return (StorageHandle)desc;
+ }
+ //no space on disk? make some space available
+ if (errno == ENOSPC)
+ freeSpace();
+ //second try
+ desc=open(filename, O_RDWR | O_CREAT, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
+ if (desc==-1 && !wroteError) {
+ //report error to syslog - once!
+ wroteError=true;
+ esyslog("OSD-Teletext: Error opening teletext file %s: %s", filename, strerror(errno));
+ }
+
+ if (desc==-1)
+ return StorageHandle();
+ else if (!seekTo(page, desc, true)) {
+ ::close(desc);
+ return StorageHandle();
+ }
+
+ if ( maxBytes && byteCount>maxBytes )
+ freeSpace();
+ return (StorageHandle)desc;
+}
+
+StorageHandle PackedStorage::openForReading(PageID page, bool countAsAccess) {
+ int desc;
+ if ( (desc=(int)LegacyStorage::openForReading(page, false))!= -1 ) {
+ if (!seekTo(page, desc, false)) {
+ //this is not an error condition here, may and shall happen!
+ ::close(desc);
+ } else {
+ return (StorageHandle)desc;
+ }
+ }
+ return StorageHandle();
+}