Mercurial > mplayer.hg
view unrar_exec.c @ 27148:858c01b81117
r26502: Document rgbtest arguments
r26057: Fix copy&paste typo in rgbtest documentation
r26198: Grayscale encoding/decoding with FFmpeg is no longer enabled, remove references
r26221: Try to fix the description of what mbcmp influences, please fix if I misunderstood the code.
r26231: better syntax for A key
r26232: added missing escapes
r26260: Experimental support for -framedrop with -correct-pts.
r26271: Mention that '-frames 0' is useful with -identify, closes bug #1046.
r26273: add "ipod" to the list of formats handled by lavf
r26297: compacted new libavformat's 'ipod' description
r26402: Enable runtime control for colorful and/or module name output
r26427: Restore grayscale decoding support with FFmpeg.
r26449: 10L, forgot to commit the documentation for the -noconfig options.
r26460: restore options alphabetical order
r26650: Update documentation for the gl2 driver to make clear gl is usually preferred.
r26674: add h264 to list of supported codecs
r26732: Mark new options Michael committed as undocumented.
r26739: Oops, remove stray .TP.
r26749: -psprobe can be used in mpeg-pes streams, too
r26762: Add a new suboption to -vo xv and -vo xvmc that allows selection
r26763: Remove '(pass 1/2)' from some lavcopts. These options really worked on
r26795: Add support for AppleIR Remote as an input under Linux systems.
r26798: Document the -noar command-line option in en/fr manpages.
r26806: Document x264's AQ options
r26853: Update gl vo section with the new force-pbo suboption.
r26909: Add a slave command to stop stream playback.
r26979: small spelling/wording fixes
r26986: Document VIDIXIVTVALPHA environment variable.
r26997: Fix codec-specific options syntax declaration to be less confusing and wrong.
r27057: Ability for specifying TV standard individually for each TV channel.
r27132: Fix/restore the description of the rectangle video filter.
previously applied:
r27169: add missing escapes and full stops for scaletempo filter
r27179: remove two trailing whitespaces
author | kraymer |
---|---|
date | Mon, 30 Jun 2008 19:35:45 +0000 |
parents | 0f42fb42843c |
children | 32725ca88fed |
line wrap: on
line source
/* * List files and extract file from rars by using external executable unrar. * * Copyright (C) 2005 Jindrich Makovicka <makovick gmail com> * Copyright (C) 2007 Ulion <ulion2002 gmail com> * * This file is part of MPlayer. * * MPlayer is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * MPlayer is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License along * with MPlayer; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. */ #include <sys/wait.h> #include <unistd.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <string.h> #include <errno.h> #include <locale.h> #include "unrar_exec.h" #include "mp_msg.h" #define UNRAR_LIST 1 #define UNRAR_EXTRACT 2 char* unrar_executable = NULL; static FILE* launch_pipe(pid_t *apid, const char *executable, int action, const char *archive, const char *filename) { if (!executable || access(executable, R_OK | X_OK)) return NULL; if (access(archive, R_OK)) return NULL; { int mypipe[2]; pid_t pid; if (pipe(mypipe)) { mp_msg(MSGT_GLOBAL, MSGL_ERR, "UnRAR: Cannot create pipe.\n"); return NULL; } pid = fork(); if (pid == 0) { /* This is the child process. Execute the unrar executable. */ close(mypipe[0]); // Close MPlayer's stdin, stdout and stderr so the unrar binary // can not mess them up. // TODO: Close all other files except the pipe. close(0); close(1); close(2); // Assign new stdin, stdout and stderr and check they actually got the // right descriptors. if (open("/dev/null", O_RDONLY) != 0 || dup(mypipe[1]) != 1 || open("/dev/null", O_WRONLY) != 2) _exit(EXIT_FAILURE); if (action == UNRAR_LIST) execl(executable, executable, "v", archive, NULL); else if (action == UNRAR_EXTRACT) execl(executable, executable, "p", "-inul", "-p-", archive,filename,NULL); mp_msg(MSGT_GLOBAL, MSGL_ERR, "UnRAR: Cannot execute %s\n", executable); _exit(EXIT_FAILURE); } if (pid < 0) { /* The fork failed. Report failure. */ mp_msg(MSGT_GLOBAL, MSGL_ERR, "UnRAR: Fork failed\n"); return NULL; } /* This is the parent process. Prepare the pipe stream. */ close(mypipe[1]); *apid = pid; if (action == UNRAR_LIST) mp_msg(MSGT_GLOBAL, MSGL_V, "UnRAR: call unrar with command line: %s v %s\n", executable, archive); else if (action == UNRAR_EXTRACT) mp_msg(MSGT_GLOBAL, MSGL_V, "UnRAR: call unrar with command line: %s p -inul -p- %s %s\n", executable, archive, filename); return fdopen(mypipe[0], "r"); } } #define ALLOC_INCR 1 * 1024 * 1024 int unrar_exec_get(unsigned char **output, unsigned long *size, const char *filename, const char *rarfile) { int bufsize = ALLOC_INCR, bytesread; pid_t pid; int status = 0; FILE *rar_pipe; rar_pipe=launch_pipe(&pid,unrar_executable,UNRAR_EXTRACT,rarfile,filename); if (!rar_pipe) return 0; *size = 0; *output = malloc(bufsize); while (*output) { bytesread=fread(*output+*size, 1, bufsize-*size, rar_pipe); if (bytesread <= 0) break; *size += bytesread; if (*size == bufsize) { char *p; bufsize += ALLOC_INCR; p = realloc(*output, bufsize); if (!p) free(*output); *output = p; } } fclose(rar_pipe); pid = waitpid(pid, &status, 0); if (!*output || !*size || (pid == -1 && errno != ECHILD) || (pid > 0 && status)) { free(*output); *output = NULL; *size = 0; return 0; } if (bufsize > *size) { char *p = realloc(*output, *size); if (p) *output = p; } mp_msg(MSGT_GLOBAL, MSGL_V, "UnRAR: got file %s len %lu\n", filename,*size); return 1; } #define PARSE_NAME 0 #define PARSE_PROPS 1 int unrar_exec_list(const char *rarfile, ArchiveList_struct **list) { char buf[1024], fname[1024]; char *p; pid_t pid; int status = 0, file_num = -1, ignore_next_line = 0, state = PARSE_NAME; FILE *rar_pipe; ArchiveList_struct *alist = NULL, *current = NULL, *new; rar_pipe = launch_pipe(&pid, unrar_executable, UNRAR_LIST, rarfile, NULL); if (!rar_pipe) return -1; while (fgets(buf, sizeof(buf), rar_pipe)) { int packsize, unpsize, ratio, day, month, year, hour, min; int llen = strlen(buf); // If read nothing, we got a file_num -1. if (file_num == -1) file_num = 0; if (buf[llen-1] != '\n') // The line is too long, ignore it. ignore_next_line = 2; if (ignore_next_line) { --ignore_next_line; state = PARSE_NAME; continue; } // Trim the line. while (llen > 0 && strchr(" \t\n\r\v\f", buf[llen-1])) --llen; buf[llen] = '\0'; p = buf; while (*p && strchr(" \t\n\r\v\f", *p)) ++p; if (!*p) { state = PARSE_NAME; continue; } if (state == PARSE_PROPS && sscanf(p, "%d %d %d%% %d-%d-%d %d:%d", &unpsize, &packsize, &ratio, &day, &month, &year, &hour, &min) == 8) { new = calloc(1, sizeof(ArchiveList_struct)); if (!new) { file_num = -1; break; } if (!current) alist = new; else current->next = new; current = new; current->item.Name = strdup(fname); state = PARSE_NAME; if (!current->item.Name) { file_num = -1; break; } current->item.PackSize = packsize; current->item.UnpSize = unpsize; ++file_num; continue; } strcpy(fname, p); state = PARSE_PROPS; } fclose(rar_pipe); pid = waitpid(pid, &status, 0); if (file_num < 0 || (pid == -1 && errno != ECHILD) || (pid > 0 && status)) { unrar_exec_freelist(alist); return -1; } if (!alist) return -1; *list = alist; mp_msg(MSGT_GLOBAL, MSGL_V, "UnRAR: list got %d files\n", file_num); return file_num; } void unrar_exec_freelist(ArchiveList_struct *list) { ArchiveList_struct* tmp; while (list) { tmp = list->next; free(list->item.Name); free(list); list = tmp; } }