1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// FileStreams.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifndef _WIN32
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <fcntl.h>
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <unistd.h>
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <errno.h>
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef SUPPORT_DEVICE_FILE
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../../C/Alloc.h"
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "../../Common/Defs.h"
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
15baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
16baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "FileStreams.h"
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
18baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic inline HRESULT ConvertBoolToHRESULT(bool result)
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef _WIN32
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (result)
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  DWORD lastError = ::GetLastError();
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (lastError == 0)
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return HRESULT_FROM_WIN32(lastError);
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return result ? S_OK: E_FAIL;
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
33baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const UInt32 kClusterSize = 1 << 18;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCInFileStream::CInFileStream():
35f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  #ifdef SUPPORT_DEVICE_FILE
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  VirtPos(0),
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  PhyPos(0),
38cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  Buf(0),
39cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  BufSize(0),
40f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  #endif
41f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  SupportHardLinks(false),
42f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  Callback(NULL),
43f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  CallbackRef(0)
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
45baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
47baa3858d3f5d128a5c8466b700098109edcad5f2repo syncCInFileStream::~CInFileStream()
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef SUPPORT_DEVICE_FILE
50cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  MidFree(Buf);
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
52f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
53f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  if (Callback)
54f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    Callback->InFileStream_On_Destroy(CallbackRef);
55baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
57baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_WIN_FILE
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef SUPPORT_DEVICE_FILE
62cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = 0;
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (size == 0)
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (File.IsDeviceFile)
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
68cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (File.SizeDefined)
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
70cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (VirtPos >= File.Size)
71cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        return VirtPos == File.Size ? S_OK : E_FAIL;
72cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      UInt64 rem = File.Size - VirtPos;
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (size > rem)
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        size = (UInt32)rem;
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (;;)
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      const UInt32 mask = kClusterSize - 1;
79cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      const UInt64 mask2 = ~(UInt64)mask;
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt64 alignedPos = VirtPos & mask2;
81cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (BufSize > 0 && BufStartPos == alignedPos)
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        UInt32 pos = (UInt32)VirtPos & mask;
84cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        if (pos >= BufSize)
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return S_OK;
86cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        UInt32 rem = MyMin(BufSize - pos, size);
87cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        memcpy(data, Buf + pos, rem);
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        VirtPos += rem;
89cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        if (processedSize)
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          *processedSize += rem;
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return S_OK;
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
94cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      bool useBuf = false;
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if ((VirtPos & mask) != 0 || ((ptrdiff_t)data & mask) != 0 )
96cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        useBuf = true;
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      else
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        UInt64 end = VirtPos + size;
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if ((end & mask) != 0)
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        {
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          end &= mask2;
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          if (end <= VirtPos)
104cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky            useBuf = true;
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          else
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync            size = (UInt32)(end - VirtPos);
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        }
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
109cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (!useBuf)
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        break;
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (alignedPos != PhyPos)
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        UInt64 realNewPosition;
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        bool result = File.Seek(alignedPos, FILE_BEGIN, realNewPosition);
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        if (!result)
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return ConvertBoolToHRESULT(result);
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        PhyPos = realNewPosition;
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
120cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      BufStartPos = alignedPos;
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt32 readSize = kClusterSize;
122cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (File.SizeDefined)
123cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        readSize = (UInt32)MyMin(File.Size - PhyPos, (UInt64)kClusterSize);
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
125cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (!Buf)
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
127cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        Buf = (Byte *)MidAlloc(kClusterSize);
128cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky        if (!Buf)
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          return E_OUTOFMEMORY;
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
131cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      bool result = File.Read1(Buf, readSize, BufSize);
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!result)
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return ConvertBoolToHRESULT(result);
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
135cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      if (BufSize == 0)
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return S_OK;
137cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      PhyPos += BufSize;
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (VirtPos != PhyPos)
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      UInt64 realNewPosition;
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      bool result = File.Seek(VirtPos, FILE_BEGIN, realNewPosition);
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!result)
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return ConvertBoolToHRESULT(result);
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      PhyPos = VirtPos = realNewPosition;
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 realProcessedSize;
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool result = File.ReadPart(data, size, realProcessedSize);
153cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = realProcessedSize;
155f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef SUPPORT_DEVICE_FILE
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  VirtPos += realProcessedSize;
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  PhyPos += realProcessedSize;
159baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
160f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
161f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  if (result)
162f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    return S_OK;
163f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
164f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  {
165f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    DWORD error = ::GetLastError();
166f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
167f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    if (Callback)
168f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      return Callback->InFileStream_On_Error(CallbackRef, error);
169f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    if (error == 0)
170f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      return E_FAIL;
171f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
172f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    return HRESULT_FROM_WIN32(error);
173f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  }
174f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
175baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
176baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
177cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
178baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = 0;
179baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ssize_t res = File.Read(data, (size_t)size);
180baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == -1)
181f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  {
182f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    if (Callback)
183f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka      return Callback->InFileStream_On_Error(CallbackRef, E_FAIL);
184baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
185f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  }
186cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
187baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = (UInt32)res;
188baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
189baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
190baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
191baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
192baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
193baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef UNDER_CE
194baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
195baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
196cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  size_t s2 = fread(data, 1, size, stdin);
197cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  int error = ferror(stdin);
198cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
199baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = s2;
200cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (s2 <= size && error == 0)
201cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return S_OK;
202cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return E_FAIL;
203baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
204baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#else
205baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CStdInFileStream::Read(void *data, UInt32 size, UInt32 *processedSize)
206baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
207baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef _WIN32
208baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
209baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  DWORD realProcessedSize;
210baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 sizeTemp = (1 << 20);
211baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (sizeTemp > size)
212baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    sizeTemp = size;
213baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  BOOL res = ::ReadFile(GetStdHandle(STD_INPUT_HANDLE), data, sizeTemp, &realProcessedSize, NULL);
214cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
215baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = realProcessedSize;
216baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == FALSE && GetLastError() == ERROR_BROKEN_PIPE)
217baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
218baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return ConvertBoolToHRESULT(res != FALSE);
219baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
220baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
221baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
222cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
223baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = 0;
224baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ssize_t res;
225baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  do
226baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
227baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    res = read(0, data, (size_t)size);
228baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
229baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (res < 0 && (errno == EINTR));
230baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == -1)
231baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
232cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
233baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = (UInt32)res;
234baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
235baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
236baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
237baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
238baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
239baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
240baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
241cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CInFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
242baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
243baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (seekOrigin >= 3)
244baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return STG_E_INVALIDFUNCTION;
245baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
246baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_WIN_FILE
247baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
248baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef SUPPORT_DEVICE_FILE
249cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (File.IsDeviceFile && (File.SizeDefined || seekOrigin != STREAM_SEEK_END))
250baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
251cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    switch (seekOrigin)
252baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
253baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      case STREAM_SEEK_SET: break;
254cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      case STREAM_SEEK_CUR: offset += VirtPos; break;
255cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      case STREAM_SEEK_END: offset += File.Size; break;
256baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      default: return STG_E_INVALIDFUNCTION;
257baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
258cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (offset < 0)
259cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      return HRESULT_WIN32_ERROR_NEGATIVE_SEEK;
260cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    VirtPos = offset;
261baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (newPosition)
262cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky      *newPosition = offset;
263baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return S_OK;
264baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
265baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
266baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
267baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 realNewPosition;
268baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool result = File.Seek(offset, seekOrigin, realNewPosition);
269baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
270baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef SUPPORT_DEVICE_FILE
271baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  PhyPos = VirtPos = realNewPosition;
272baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
273baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
274cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (newPosition)
275baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *newPosition = realNewPosition;
276baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return ConvertBoolToHRESULT(result);
277baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
278baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
279baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
280cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  off_t res = File.Seek((off_t)offset, seekOrigin);
281baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == -1)
282baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
283cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (newPosition)
284baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *newPosition = (UInt64)res;
285baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
286baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
287baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
288baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
289baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
290baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CInFileStream::GetSize(UInt64 *size)
291baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
292baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return ConvertBoolToHRESULT(File.GetLength(*size));
293baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
294baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
295cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#ifdef USE_WIN_FILE
296cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
297cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CInFileStream::GetProps(UInt64 *size, FILETIME *cTime, FILETIME *aTime, FILETIME *mTime, UInt32 *attrib)
298cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
299cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  BY_HANDLE_FILE_INFORMATION info;
300cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (File.GetFileInformation(&info))
301cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
302cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (size) *size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
303cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (cTime) *cTime = info.ftCreationTime;
304cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (aTime) *aTime = info.ftLastAccessTime;
305cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (mTime) *mTime = info.ftLastWriteTime;
306cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (attrib) *attrib = info.dwFileAttributes;
307cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return S_OK;
308cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
309cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return GetLastError();
310cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
311cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
312cd66d540cead3f8200b0c73bad9c276d67896c3dDavid SrbeckySTDMETHODIMP CInFileStream::GetProps2(CStreamFileProps *props)
313cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky{
314cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  BY_HANDLE_FILE_INFORMATION info;
315cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (File.GetFileInformation(&info))
316cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  {
317cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    props->Size = (((UInt64)info.nFileSizeHigh) << 32) + info.nFileSizeLow;
318cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    props->VolID = info.dwVolumeSerialNumber;
319cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    props->FileID_Low = (((UInt64)info.nFileIndexHigh) << 32) + info.nFileIndexLow;
320cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    props->FileID_High = 0;
321cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    props->NumLinks = SupportHardLinks ? info.nNumberOfLinks : 1;
322cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    props->Attrib = info.dwFileAttributes;
323cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    props->CTime = info.ftCreationTime;
324cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    props->ATime = info.ftLastAccessTime;
325cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    props->MTime = info.ftLastWriteTime;
326cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    return S_OK;
327cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  }
328cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return GetLastError();
329cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky}
330cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky
331cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky#endif
332baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
333baa3858d3f5d128a5c8466b700098109edcad5f2repo sync//////////////////////////
334baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// COutFileStream
335baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
336baa3858d3f5d128a5c8466b700098109edcad5f2repo syncHRESULT COutFileStream::Close()
337baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
338baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return ConvertBoolToHRESULT(File.Close());
339baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
340baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
341baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP COutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
342baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
343baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_WIN_FILE
344baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
345baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 realProcessedSize;
346f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  bool result = File.Write(data, size, realProcessedSize);
347baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ProcessedSize += realProcessedSize;
348cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
349baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = realProcessedSize;
350baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return ConvertBoolToHRESULT(result);
351baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
352baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
353baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
354cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
355baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = 0;
356baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ssize_t res = File.Write(data, (size_t)size);
357baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == -1)
358baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
359cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
360baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = (UInt32)res;
361baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ProcessedSize += res;
362baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
363baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
364baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
365baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
366baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
367baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP COutFileStream::Seek(Int64 offset, UInt32 seekOrigin, UInt64 *newPosition)
368baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
369baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (seekOrigin >= 3)
370baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return STG_E_INVALIDFUNCTION;
371f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
372baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_WIN_FILE
373baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
374baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 realNewPosition;
375baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool result = File.Seek(offset, seekOrigin, realNewPosition);
376cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (newPosition)
377baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *newPosition = realNewPosition;
378baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return ConvertBoolToHRESULT(result);
379baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
380baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
381baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
382cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  off_t res = File.Seek((off_t)offset, seekOrigin);
383baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == -1)
384baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
385cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (newPosition)
386baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *newPosition = (UInt64)res;
387baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
388baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
389baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
390baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
391baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
392baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP COutFileStream::SetSize(UInt64 newSize)
393baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
394baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef USE_WIN_FILE
395f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
396baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 currentPos;
397baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (!File.Seek(0, FILE_CURRENT, currentPos))
398baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
399baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  bool result = File.SetLength(newSize);
400baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt64 currentPos2;
401baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  result = result && File.Seek(currentPos, currentPos2);
402baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return result ? S_OK : E_FAIL;
403f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
404baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
405f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
406baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return E_FAIL;
407f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
408baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
409baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
410baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
411f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo OsakaHRESULT COutFileStream::GetSize(UInt64 *size)
412f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka{
413f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  return ConvertBoolToHRESULT(File.GetLength(*size));
414f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka}
415f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
416baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#ifdef UNDER_CE
417f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
418baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
419baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
420baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  size_t s2 = fwrite(data, 1, size, stdout);
421cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
422baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = s2;
423cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  return (s2 == size) ? S_OK : E_FAIL;
424baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
425f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
426baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#else
427f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
428baa3858d3f5d128a5c8466b700098109edcad5f2repo syncSTDMETHODIMP CStdOutFileStream::Write(const void *data, UInt32 size, UInt32 *processedSize)
429baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
430cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
431baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = 0;
432baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
433baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #ifdef _WIN32
434f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
435baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UInt32 realProcessedSize;
436baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  BOOL res = TRUE;
437baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (size > 0)
438baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
439baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // Seems that Windows doesn't like big amounts writing to stdout.
440baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    // So we limit portions by 32KB.
441baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UInt32 sizeTemp = (1 << 15);
442baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (sizeTemp > size)
443baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      sizeTemp = size;
444baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    res = ::WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),
445baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        data, sizeTemp, (DWORD *)&realProcessedSize, NULL);
446f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka    _size += realProcessedSize;
447baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    size -= realProcessedSize;
448baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    data = (const void *)((const Byte *)data + realProcessedSize);
449cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky    if (processedSize)
450baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      *processedSize += realProcessedSize;
451baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
452baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return ConvertBoolToHRESULT(res != FALSE);
453baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
454baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #else
455baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
456baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  ssize_t res;
457f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
458baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  do
459baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
460baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    res = write(1, data, (size_t)size);
461baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
462baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (res < 0 && (errno == EINTR));
463f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
464baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  if (res == -1)
465baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    return E_FAIL;
466f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka
467f955a79a9fffb09826cf7547f70d08c3798a2f50Tetsuo Osaka  _size += (size_t)res;
468cd66d540cead3f8200b0c73bad9c276d67896c3dDavid Srbecky  if (processedSize)
469baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    *processedSize = (UInt32)res;
470baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  return S_OK;
471baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
472baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  #endif
473baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
474baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
475baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#endif
476