fix rawfile
[enigma2.git] / lib / base / rawfile.cpp
1 #include <unistd.h>
2 #include <fcntl.h>
3 #include <lib/base/rawfile.h>
4 #include <lib/base/eerror.h>
5
6 eRawFile::eRawFile()
7 {
8         m_fd = -1;
9         m_splitsize = 0;
10         m_totallength = 0;
11         m_current_offset = 0;
12         m_base_offset = 0;
13         m_last_offset = 0;
14         m_nrfiles = 0;
15         m_current_file = 0;
16 }
17
18 eRawFile::~eRawFile()
19 {
20         close();
21 }
22
23 int eRawFile::open(const char *filename)
24 {
25         close();
26         m_basename = filename;
27         scan();
28         m_current_offset = 0;
29         m_last_offset = 0;
30         m_fd = ::open(filename, O_RDONLY | O_LARGEFILE);
31         return m_fd;
32 }
33
34 void eRawFile::setfd(int fd)
35 {
36         close();
37         m_nrfiles = 1;
38         m_fd = fd;
39 }
40
41 off_t eRawFile::lseek(off_t offset, int whence)
42 {
43 //      eDebug("lseek: %lld, %d", offset, whence);
44                 /* if there is only one file, use the native lseek - the file could be growing! */
45         if (m_nrfiles < 2)
46                 return ::lseek(m_fd, offset, whence);
47         switch (whence)
48         {
49         case SEEK_SET:
50                 m_current_offset = offset;
51                 break;
52         case SEEK_CUR:
53                 m_current_offset += offset;
54                 break;
55         case SEEK_END:
56                 m_current_offset = m_totallength + offset;
57                 break;
58         }
59
60         if (m_current_offset < 0)
61                 m_current_offset = 0;
62         return m_current_offset;
63 }
64
65 int eRawFile::close()
66 {
67         int ret = ::close(m_fd);
68         m_fd = -1;
69         return ret;
70 }
71
72 ssize_t eRawFile::read(void *buf, size_t count)
73 {
74 //      eDebug("read: %p, %d", buf, count);
75         switchOffset(m_current_offset);
76         
77         if (m_nrfiles >= 2)
78         {
79                 if (m_current_offset + count > m_totallength)
80                         count = m_totallength - m_current_offset;
81                 if (count < 0)
82                         return 0;
83         }
84         
85         int ret = ::read(m_fd, buf, count);
86         if (ret > 0)
87                 m_current_offset = m_last_offset += ret;
88         return ret;
89 }
90
91 int eRawFile::valid()
92 {
93         return m_fd != -1;
94 }
95
96 void eRawFile::scan()
97 {
98         m_nrfiles = 0;
99         m_totallength = 0;
100         while (m_nrfiles < 1000) /* .999 is the last possible */
101         {
102                 int f = openFile(m_nrfiles);
103                 if (f < 0)
104                         break;
105                 if (!m_nrfiles)
106                         m_splitsize = ::lseek(f, 0, SEEK_END);
107                 m_totallength += ::lseek(f, 0, SEEK_END);
108                 ::close(f);
109                 
110                 ++m_nrfiles;
111         }
112 //      eDebug("found %d files, splitsize: %llx, totallength: %llx", m_nrfiles, m_splitsize, m_totallength);
113 }
114
115 int eRawFile::switchOffset(off_t off)
116 {
117         if (m_splitsize)
118         {
119                 int filenr = off / m_splitsize;
120                 if (filenr >= m_nrfiles)
121                         filenr = m_nrfiles - 1;
122                 if (filenr != m_current_file)
123                 {       
124 //                      eDebug("-> %d", filenr);
125                         close();
126                         m_fd = openFile(filenr);
127                         m_last_offset = m_base_offset = m_splitsize * filenr;
128                         m_current_file = filenr;
129                 }
130         } else
131                 m_base_offset = 0;
132         
133         if (off != m_last_offset)
134         {
135 //              eDebug("%llx != %llx", off, m_last_offset);
136                 m_last_offset = ::lseek(m_fd, off - m_base_offset, SEEK_SET) + m_base_offset;
137 //              eDebug("offset now %llx", m_last_offset);
138                 return m_last_offset;
139         } else
140         {
141 //              eDebug("offset already ok");
142                 return m_last_offset;
143         }
144 }
145
146 int eRawFile::openFile(int nr)
147 {
148         std::string filename = m_basename;
149         if (nr)
150         {
151                 char suffix[5];
152                 snprintf(suffix, 5, ".%03d", nr);
153                 filename += suffix;
154         }
155         return ::open(filename.c_str(), O_RDONLY);
156 }