stream_libarchive: workaround various types of locale braindeath · mpv-player/mpv@1e70e82

2 min read Original article ↗

@@ -150,6 +150,8 @@ static bool mp_archive_check_fatal(struct mp_archive *mpa, int r)

150150

void mp_archive_free(struct mp_archive *mpa)

151151

{

152152

mp_archive_close(mpa);

153+

if (mpa && mpa->locale)

154+

freelocale(mpa->locale);

153155

talloc_free(mpa);

154156

}

155157

@@ -229,14 +231,20 @@ static bool add_volume(struct mp_log *log, struct mp_archive *mpa,

229231

vol->mpa = mpa;

230232

vol->src = src;

231233

vol->url = talloc_strdup(vol, url);

232-

return archive_read_append_callback_data(mpa->arch, vol) == ARCHIVE_OK;

234+

locale_t oldlocale = uselocale(mpa->locale);

235+

bool res = archive_read_append_callback_data(mpa->arch, vol) == ARCHIVE_OK;

236+

uselocale(oldlocale);

237+

return res;

233238

}

234239235240

struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src,

236241

int flags)

237242

{

238243

struct mp_archive *mpa = talloc_zero(NULL, struct mp_archive);

239244

mpa->log = log;

245+

mpa->locale = newlocale(LC_ALL_MASK, "C.UTF-8", (locale_t)0);

246+

if (!mpa->locale)

247+

goto err;

240248

mpa->arch = archive_read_new();

241249

mpa->primary_src = src;

242250

if (!mpa->arch)

@@ -256,6 +264,8 @@ struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src,

256264

}

257265

talloc_free(volumes);

258266267+

locale_t oldlocale = uselocale(mpa->locale);

268+259269

archive_read_support_format_7zip(mpa->arch);

260270

archive_read_support_format_iso9660(mpa->arch);

261271

archive_read_support_format_rar(mpa->arch);

@@ -275,7 +285,11 @@ struct mp_archive *mp_archive_new(struct mp_log *log, struct stream *src,

275285

archive_read_set_close_callback(mpa->arch, close_cb);

276286

if (mpa->primary_src->seekable)

277287

archive_read_set_seek_callback(mpa->arch, seek_cb);

278-

if (archive_read_open1(mpa->arch) < ARCHIVE_OK)

288+

bool fail = archive_read_open1(mpa->arch) < ARCHIVE_OK;

289+290+

uselocale(oldlocale);

291+292+

if (fail)

279293

goto err;

280294

return mpa;

281295

@@ -295,6 +309,9 @@ bool mp_archive_next_entry(struct mp_archive *mpa)

295309

if (!mpa->arch)

296310

return false;

297311312+

locale_t oldlocale = uselocale(mpa->locale);

313+

bool success = false;

314+298315

while (!mp_cancel_test(mpa->primary_src->cancel)) {

299316

struct archive_entry *entry;

300317

int r = archive_read_next_header(mpa->arch, &entry);

@@ -319,10 +336,13 @@ bool mp_archive_next_entry(struct mp_archive *mpa)

319336

mpa->entry = entry;

320337

mpa->entry_filename = talloc_strdup(mpa, fn);

321338

mpa->entry_num += 1;

322-

return true;

339+

success = true;

340+

break;

323341

}

324342325-

return false;

343+

uselocale(oldlocale);

344+345+

return success;

326346

}

327347328348

struct priv {

@@ -344,9 +364,11 @@ static int reopen_archive(stream_t *s)

344364

struct mp_archive *mpa = p->mpa;

345365

while (mp_archive_next_entry(mpa)) {

346366

if (strcmp(p->entry_name, mpa->entry_filename) == 0) {

367+

locale_t oldlocale = uselocale(mpa->locale);

347368

p->entry_size = -1;

348369

if (archive_entry_size_is_set(mpa->entry))

349370

p->entry_size = archive_entry_size(mpa->entry);

371+

uselocale(oldlocale);

350372

return STREAM_OK;

351373

}

352374

}

@@ -362,6 +384,7 @@ static int archive_entry_fill_buffer(stream_t *s, char *buffer, int max_len)

362384

struct priv *p = s->priv;

363385

if (!p->mpa)

364386

return 0;

387+

locale_t oldlocale = uselocale(p->mpa->locale);

365388

int r = archive_read_data(p->mpa->arch, buffer, max_len);

366389

if (r < 0) {

367390

MP_ERR(s, "%s\n", archive_error_string(p->mpa->arch));

@@ -370,6 +393,7 @@ static int archive_entry_fill_buffer(stream_t *s, char *buffer, int max_len)

370393

p->mpa = NULL;

371394

}

372395

}

396+

uselocale(oldlocale);

373397

return r;

374398

}

375399

@@ -378,7 +402,9 @@ static int archive_entry_seek(stream_t *s, int64_t newpos)

378402

struct priv *p = s->priv;

379403

if (!p->mpa)

380404

return -1;

405+

locale_t oldlocale = uselocale(p->mpa->locale);

381406

int r = archive_seek_data(p->mpa->arch, newpos, SEEK_SET);

407+

uselocale(oldlocale);

382408

if (r >= 0)

383409

return 1;

384410

if (mp_archive_check_fatal(p->mpa, r)) {

@@ -404,15 +430,18 @@ static int archive_entry_seek(stream_t *s, int64_t newpos)

404430

return -1;

405431406432

int size = MPMIN(newpos - s->pos, sizeof(buffer));

433+

oldlocale = uselocale(p->mpa->locale);

407434

r = archive_read_data(p->mpa->arch, buffer, size);

408435

if (r < 0) {

409436

MP_ERR(s, "%s\n", archive_error_string(p->mpa->arch));

437+

uselocale(oldlocale);

410438

if (mp_archive_check_fatal(p->mpa, r)) {

411439

mp_archive_free(p->mpa);

412440

p->mpa = NULL;

413441

}

414442

return -1;

415443

}

444+

uselocale(oldlocale);

416445

s->pos += r;

417446

}

418447

}