Skip to content

Commit 7859ee3

Browse files
committed
Fix improper handling of unicode in the cachepath argument
Fix handling of long filenames on windows No longer create the directory structure when trying to open a cache file
1 parent 8dc0b01 commit 7859ee3

File tree

3 files changed

+52
-17
lines changed

3 files changed

+52
-17
lines changed

src/avisynth.cpp

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -71,9 +71,9 @@ class AvisynthVideoSource : public IClip {
7171
int64_t FPSDen;
7272
bool RFF;
7373
public:
74-
AvisynthVideoSource(const char *Source, int Track, int ViewID,
74+
AvisynthVideoSource(const char *RawSource, int Track, int ViewID,
7575
int AFPSNum, int AFPSDen, bool RFF, int Threads, int SeekPreRoll, bool EnableDrefs, bool UseAbsolutePath,
76-
int CacheMode, const char *CachePath, int CacheSize, const char *HWDevice, int ExtraHWFrames,
76+
int CacheMode, const char *RawCachePath, int CacheSize, const char *HWDevice, int ExtraHWFrames,
7777
const char *Timecodes, int StartNumber, int VariableFormat, int MaxDecoders, bool HWFallback, IScriptEnvironment *Env)
7878
: FPSNum(AFPSNum), FPSDen(AFPSDen), RFF(RFF) {
7979

@@ -95,11 +95,14 @@ class AvisynthVideoSource : public IClip {
9595
if (StartNumber >= 0)
9696
Opts["start_number"] = std::to_string(StartNumber);
9797

98+
std::filesystem::path Source(CreateProbablyUTF8Path(RawSource));
99+
std::filesystem::path CachePath(CreateProbablyUTF8Path(RawCachePath));
100+
98101
try {
99-
V.reset(new BestVideoSource(CreateProbablyUTF8Path(Source), HWDevice ? HWDevice : "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath, &Opts));
102+
V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath, &Opts));
100103
} catch (BestSourceHWDecoderException &) {
101104
if (HWFallback)
102-
V.reset(new BestVideoSource(CreateProbablyUTF8Path(Source), "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath, &Opts));
105+
V.reset(new BestVideoSource(Source, "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath, &Opts));
103106
else
104107
throw;
105108
}
@@ -310,17 +313,20 @@ class AvisynthAudioSource : public IClip {
310313
VideoInfo VI = {};
311314
std::unique_ptr<BestAudioSource> A;
312315
public:
313-
AvisynthAudioSource(const char *Source, int Track,
314-
int AdjustDelay, int Threads, bool EnableDrefs, bool UseAbsolutePath, double DrcScale, int CacheMode, const char *CachePath, int CacheSize, int MaxDecoders, IScriptEnvironment *Env) {
316+
AvisynthAudioSource(const char *RawSource, int Track,
317+
int AdjustDelay, int Threads, bool EnableDrefs, bool UseAbsolutePath, double DrcScale, int CacheMode, const char *RawCachePath, int CacheSize, int MaxDecoders, IScriptEnvironment *Env) {
315318

316319
std::map<std::string, std::string> Opts;
317320
if (EnableDrefs)
318321
Opts["enable_drefs"] = "1";
319322
if (UseAbsolutePath)
320323
Opts["use_absolute_path"] = "1";
321324

325+
std::filesystem::path Source(CreateProbablyUTF8Path(RawSource));
326+
std::filesystem::path CachePath(CreateProbablyUTF8Path(RawCachePath));
327+
322328
try {
323-
A.reset(new BestAudioSource(CreateProbablyUTF8Path(Source), Track, AdjustDelay, Threads, CacheMode, CachePath ? CachePath : "", &Opts, DrcScale));
329+
A.reset(new BestAudioSource(Source, Track, AdjustDelay, Threads, CacheMode, CachePath, &Opts, DrcScale));
324330

325331
A->SetMaxDecoderInstances(MaxDecoders);
326332
A->SelectFormatSet(0);

src/bsshared.cpp

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,30 @@ static std::filesystem::path MangleCachePath(const std::filesystem::path &CacheB
120120
return CachePath.make_preferred();
121121
}
122122

123+
#ifdef _WIN32
124+
static bool TryLongPath(const std::filesystem::path &Path) {
125+
const auto &WPath = Path.native();
126+
return (WPath.substr(0, 4) != L"\\\\?\\") && (WPath.length() > MAX_PATH - 10);
127+
}
128+
129+
static std::filesystem::path ConvertToLongPath(const std::filesystem::path &Path) {
130+
const auto &WPath = Path.native();
131+
std::filesystem::path Result(L"\\\\?\\");
132+
if (WPath.substr(0, 2) == L"\\\\") {
133+
Result += L"UNC\\";
134+
Result += WPath.substr(2);
135+
} else {
136+
Result += Path;
137+
}
138+
return Result;
139+
}
140+
#endif
141+
123142
file_ptr_t OpenNormalFile(const std::filesystem::path &Filename, bool Write) {
124143
#ifdef _WIN32
125144
file_ptr_t F(_wfopen(Filename.c_str(), Write ? L"wb" : L"rb"));
145+
if (!F && TryLongPath(Filename))
146+
F.reset(_wfopen(ConvertToLongPath(Filename).c_str(), Write ? L"wb" : L"rb"));
126147
#else
127148
file_ptr_t F(fopen(Filename.c_str(), Write ? "wb" : "rb"));
128149
#endif
@@ -138,8 +159,14 @@ file_ptr_t OpenCacheFile(bool AbsolutePath, const std::filesystem::path &CachePa
138159
CacheFile = MangleCachePath(CachePath.empty() ? GetDefaultCacheSubTreePath() : CachePath, Source);
139160

140161
CacheFile += "." + std::to_string(Track) + ".bsindex";
141-
std::error_code ec;
142-
std::filesystem::create_directories(CacheFile.parent_path(), ec);
162+
if (Write) {
163+
std::error_code ec;
164+
std::filesystem::create_directories(CacheFile.parent_path(), ec);
165+
#ifdef _WIN32
166+
if (ec && TryLongPath(CacheFile))
167+
std::filesystem::create_directories(ConvertToLongPath(CacheFile.parent_path()), ec);
168+
#endif
169+
}
143170
return OpenNormalFile(CacheFile, Write);
144171
}
145172

src/vapoursynth.cpp

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -132,7 +132,8 @@ static void VS_CC CreateBestVideoSource(const VSMap *In, VSMap *Out, void *, VSC
132132

133133
int err;
134134
std::filesystem::path Source = CreateProbablyUTF8Path(vsapi->mapGetData(In, "source", 0, nullptr));
135-
const char *CachePath = vsapi->mapGetData(In, "cachepath", 0, &err);
135+
const char *RawCachePath = vsapi->mapGetData(In, "cachepath", 0, &err);
136+
std::filesystem::path CachePath = CreateProbablyUTF8Path(RawCachePath ? RawCachePath : "");
136137
const char *HWDevice = vsapi->mapGetData(In, "hwdevice", 0, &err);
137138
const char *Timecodes = vsapi->mapGetData(In, "timecodes", 0, &err);
138139
int Track = vsapi->mapGetIntSaturated(In, "track", 0, &err);
@@ -208,21 +209,21 @@ static void VS_CC CreateBestVideoSource(const VSMap *In, VSMap *Out, void *, VSC
208209
return true;
209210
};
210211
try {
211-
D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath ? CachePath : "", &Opts, ProgressCB));
212+
D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath, &Opts, ProgressCB));
212213
} catch (BestSourceHWDecoderException &) {
213214
if (HWFallback) {
214-
D->V.reset(new BestVideoSource(Source, "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath ? CachePath : "", &Opts, ProgressCB));
215+
D->V.reset(new BestVideoSource(Source, "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath, &Opts, ProgressCB));
215216
} else {
216217
vsapi->logMessage(mtInformation, ("VideoSource track #" + std::to_string(Track) + " using CPU decoding fallback").c_str(), Core);
217218
throw;
218219
}
219220
}
220221
} else {
221222
try {
222-
D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath ? CachePath : "", &Opts));
223+
D->V.reset(new BestVideoSource(Source, HWDevice ? HWDevice : "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath, &Opts));
223224
} catch (BestSourceHWDecoderException &) {
224225
if (HWFallback) {
225-
D->V.reset(new BestVideoSource(Source, "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath ? CachePath : "", &Opts));
226+
D->V.reset(new BestVideoSource(Source, "", ExtraHWFrames, Track, ViewID, Threads, CacheMode, CachePath, &Opts));
226227
} else {
227228
vsapi->logMessage(mtInformation, ("VideoSource track #" + std::to_string(Track) + " using CPU decoding fallback").c_str(), Core);
228229
throw;
@@ -333,7 +334,8 @@ static void VS_CC CreateBestAudioSource(const VSMap *In, VSMap *Out, void *, VSC
333334

334335
int err;
335336
std::filesystem::path Source = CreateProbablyUTF8Path(vsapi->mapGetData(In, "source", 0, nullptr));
336-
const char *CachePath = vsapi->mapGetData(In, "cachepath", 0, &err);
337+
const char *RawCachePath = vsapi->mapGetData(In, "cachepath", 0, &err);
338+
std::filesystem::path CachePath = CreateProbablyUTF8Path(RawCachePath ? RawCachePath : "");
337339
int Track = vsapi->mapGetIntSaturated(In, "track", 0, &err);
338340
if (err)
339341
Track = -1;
@@ -361,7 +363,7 @@ static void VS_CC CreateBestAudioSource(const VSMap *In, VSMap *Out, void *, VSC
361363
if (ShowProgress) {
362364
auto NextUpdate = std::chrono::high_resolution_clock::now();
363365
int LastValue = -1;
364-
D->A.reset(new BestAudioSource(Source, Track, AdjustDelay, Threads, CacheMode, CachePath ? CachePath : "", &Opts, DrcScale,
366+
D->A.reset(new BestAudioSource(Source, Track, AdjustDelay, Threads, CacheMode, CachePath, &Opts, DrcScale,
365367
[vsapi, Core, &NextUpdate, &LastValue](int Track, int64_t Cur, int64_t Total) {
366368
if (NextUpdate < std::chrono::high_resolution_clock::now()) {
367369
if (Total == INT64_MAX && Cur == Total) {
@@ -379,7 +381,7 @@ static void VS_CC CreateBestAudioSource(const VSMap *In, VSMap *Out, void *, VSC
379381
}));
380382

381383
} else {
382-
D->A.reset(new BestAudioSource(Source, Track, AdjustDelay, Threads, CacheMode, CachePath ? CachePath : "", &Opts, DrcScale));
384+
D->A.reset(new BestAudioSource(Source, Track, AdjustDelay, Threads, CacheMode, CachePath, &Opts, DrcScale));
383385
}
384386

385387
D->A->SetMaxDecoderInstances(MaxDecoders);

0 commit comments

Comments
 (0)