1// Copyright (c) 2010 The WebM project authors. All Rights Reserved.
2//
3// Use of this source code is governed by a BSD-style license
4// that can be found in the LICENSE file in the root of the source
5// tree. An additional intellectual property rights grant can be found
6// in the file PATENTS.  All contributing project authors may
7// be found in the AUTHORS file in the root of the source tree.
8#include "mkvparser/mkvreader.h"
9
10#include <sys/types.h>
11
12#include <cassert>
13
14namespace mkvparser {
15
16MkvReader::MkvReader() : m_file(NULL), reader_owns_file_(true) {}
17
18MkvReader::MkvReader(FILE* fp) : m_file(fp), reader_owns_file_(false) {
19  GetFileSize();
20}
21
22MkvReader::~MkvReader() {
23  if (reader_owns_file_)
24    Close();
25  m_file = NULL;
26}
27
28int MkvReader::Open(const char* fileName) {
29  if (fileName == NULL)
30    return -1;
31
32  if (m_file)
33    return -1;
34
35#ifdef _MSC_VER
36  const errno_t e = fopen_s(&m_file, fileName, "rb");
37
38  if (e)
39    return -1;  // error
40#else
41  m_file = fopen(fileName, "rb");
42
43  if (m_file == NULL)
44    return -1;
45#endif
46  return !GetFileSize();
47}
48
49bool MkvReader::GetFileSize() {
50  if (m_file == NULL)
51    return false;
52#ifdef _MSC_VER
53  int status = _fseeki64(m_file, 0L, SEEK_END);
54
55  if (status)
56    return false;  // error
57
58  m_length = _ftelli64(m_file);
59#else
60  fseek(m_file, 0L, SEEK_END);
61  m_length = ftell(m_file);
62#endif
63  assert(m_length >= 0);
64
65  if (m_length < 0)
66    return false;
67
68#ifdef _MSC_VER
69  status = _fseeki64(m_file, 0L, SEEK_SET);
70
71  if (status)
72    return false;  // error
73#else
74  fseek(m_file, 0L, SEEK_SET);
75#endif
76
77  return true;
78}
79
80void MkvReader::Close() {
81  if (m_file != NULL) {
82    fclose(m_file);
83    m_file = NULL;
84  }
85}
86
87int MkvReader::Length(long long* total, long long* available) {
88  if (m_file == NULL)
89    return -1;
90
91  if (total)
92    *total = m_length;
93
94  if (available)
95    *available = m_length;
96
97  return 0;
98}
99
100int MkvReader::Read(long long offset, long len, unsigned char* buffer) {
101  if (m_file == NULL)
102    return -1;
103
104  if (offset < 0)
105    return -1;
106
107  if (len < 0)
108    return -1;
109
110  if (len == 0)
111    return 0;
112
113  if (offset >= m_length)
114    return -1;
115
116#ifdef _MSC_VER
117  const int status = _fseeki64(m_file, offset, SEEK_SET);
118
119  if (status)
120    return -1;  // error
121#else
122  fseeko(m_file, static_cast<off_t>(offset), SEEK_SET);
123#endif
124
125  const size_t size = fread(buffer, 1, len, m_file);
126
127  if (size < size_t(len))
128    return -1;  // error
129
130  return 0;  // success
131}
132
133}  // namespace mkvparser
134