/* * join_path_components - join two path components, inserting a slash * * ret_path is the output area (must be of size MAXPGPATH) * * ret_path can be the same as head, but not the same as tail. */ void join_path_components(char *ret_path, const char *head, const char *tail) { if (ret_path != head) strlcpy(ret_path, head, MAXPGPATH); /* * Remove any leading "." and ".." in the tail component, adjusting head * as needed. */ for (;;) { if (tail[0] == '.' && IS_DIR_SEP(tail[1])) { tail += 2; } else if (tail[0] == '.' && tail[1] == '\0') { tail += 1; break; } else if (tail[0] == '.' && tail[1] == '.' && IS_DIR_SEP(tail[2])) { trim_directory(ret_path); tail += 3; } else if (tail[0] == '.' && tail[1] == '.' && tail[2] == '\0') { trim_directory(ret_path); tail += 2; break; } else break; } if (*tail) snprintf(ret_path + strlen(ret_path), MAXPGPATH - strlen(ret_path), "/%s", tail); }
/* * dir_strcmp: strcmp except any two DIR_SEP characters are considered equal, * and we honor filesystem case insensitivity if known */ static int dir_strcmp(const char *s1, const char *s2) { while (*s1 && *s2) { if ( #ifndef WIN32 *s1 != *s2 #else /* On windows, paths are case-insensitive */ pg_tolower((unsigned char) *s1) != pg_tolower((unsigned char) *s2) #endif && !(IS_DIR_SEP(*s1) && IS_DIR_SEP(*s2))) return (int) *s1 - (int) *s2; s1++, s2++; } if (*s1) return 1; /* s1 longer */ if (*s2) return -1; /* s2 longer */ return 0; }
/* * trim_directory * * Trim trailing directory from path, that is, remove any trailing slashes, * the last pathname component, and the slash just ahead of it --- but never * remove a leading slash. */ static void trim_directory(char *path) { char *p; if (path[0] == '\0') return; /* back up over trailing slash(es) */ for (p = path + strlen(path) - 1; IS_DIR_SEP(*p) && p > path; p--); /* back up over directory name */ for (; !IS_DIR_SEP(*p) && p > path; p--); /* if multiple slashes before directory name, remove 'em all */ for (; p > path && IS_DIR_SEP(*(p - 1)); p--); /* don't erase a leading slash */ if (p == path && IS_DIR_SEP(*p)) p++; *p = '\0'; }
static string element P2C(const_string, passed_path, boolean, env_p) { const_string p; string ret; int brace_level; unsigned len; if (passed_path) path = passed_path; /* Check if called with NULL, and no previous path (perhaps we reached the end). */ else if (!path) return NULL; /* OK, we have a non-null `path' if we get here. */ assert (path); p = path; /* Find the next colon not enclosed by braces (or the end of the path). */ brace_level = 0; while (*p != 0 && !(brace_level == 0 && (env_p ? IS_ENV_SEP (*p) : IS_DIR_SEP (*p)))) { if (*p == '{') ++brace_level; else if (*p == '}') --brace_level; ++p; } /* Return the substring starting at `path'. */ len = p - path; /* Make sure we have enough space (including the null byte). */ if (len + 1 > elt_alloc) { elt_alloc = len + 1; elt = (string)xrealloc (elt, elt_alloc); } strncpy (elt, path, len); elt[len] = 0; ret = elt; /* If we are at the end, return NULL next time. */ if (path[len] == 0) path = NULL; else path += len + 1; return ret; }
boolean kpse_absolute_p P2C(const_string, filename, boolean, relative_ok) { #ifdef VMS #include <string.h> return strcspn (filename, "]>:") != strlen (filename); #else /* not VMS */ boolean absolute = IS_DIR_SEP (*filename) #ifdef DOSISH /* Novell allows non-alphanumeric drive letters. */ || (*filename && IS_DEVICE_SEP (filename[1])) #endif /* DOSISH */ #ifdef WIN32 /* UNC names */ || (*filename == '\\' && filename[1] == '\\') #endif #ifdef AMIGA /* Colon anywhere means a device. */ || strchr (filename, ':') #endif /* AMIGA */ ; boolean explicit_relative = relative_ok #ifdef AMIGA /* Leading / is like `../' on Unix and DOS. Allow Unix syntax, too, though, because of possible patch programs like `UnixDirsII' by Martin Scott. */ && IS_DIR_SEP (*filename) || 0 #endif /* AMIGA */ && (*filename == '.' && (IS_DIR_SEP (filename[1]) || (filename[1] == '.' && IS_DIR_SEP (filename[2])))); /* FIXME: On UNIX an IS_DIR_SEP of any but the last character in the name implies relative. */ return absolute || explicit_relative; #endif /* not VMS */ }
_WCRTLINK DIR *opendir( const char *name ) { DIR *parent; int handle; char *ptr; int size; char tmp[NAME_MAX + 1]; parent = lib_malloc( sizeof( DIR ) ); if( parent == NULL ) return( NULL ); handle = RdosOpenDir( name ); if( handle == 0 ) { strcpy( tmp, name ); ptr = tmp; size = strlen( tmp ); if( size ) { ptr += size - 1; while( size ) { if( IS_DIR_SEP( *ptr ) ) break; ptr--; } ptr++; strupr( ptr ); strcpy( parent->d_match_mask, ptr ); *ptr = 0; handle = RdosOpenDir( tmp ); } else { handle = RdosOpenDir( "." ); strcpy( tmp, name ); strupr( tmp ); strcpy( parent->d_match_mask, tmp ); } } else { strcpy( parent->d_match_mask, "*" ); } if( handle == 0 ) { lib_free( parent ); return( NULL ); } parent->d_handle = handle; parent->d_entry_nr = -1; return( parent ); }
/* Parse the root part of file name, if present. Return length and optionally store pointer to char after root. */ static int _parse_root (char * name, char ** pPath) { char * start = name; if (name == NULL) return 0; /* find the root name of the volume if given */ if (isalpha (name[0]) && name[1] == ':') { /* skip past drive specifier */ name += 2; if (IS_DIR_SEP (name[0])) name++; } else if (IS_DIR_SEP (name[0]) && IS_DIR_SEP (name[1])) { int slashes = 2; name += 2; do { if (IS_DIR_SEP (*name) && --slashes == 0) break; name++; } while ( *name ); if (IS_DIR_SEP (name[0])) name++; } if (pPath) *pPath = name; return name - start; }
static int is_directory( const CHAR_TYPE *name ) /**********************************************/ { UINT_WC_TYPE curr_ch; UINT_WC_TYPE prev_ch; curr_ch = NULLCHAR; for(;;) { prev_ch = curr_ch; #if defined( __WIDECHAR__ ) || defined( __UNIX__ ) curr_ch = *name; #else curr_ch = _mbsnextc( (unsigned char *)name ); #endif if( curr_ch == NULLCHAR ) { if( IS_DIR_SEP( prev_ch ) || prev_ch == DRV_SEP ){ /* directory, need add "*.*" */ return( 2 ); } if( prev_ch == STRING( '.' ) ){ /* directory, need add "\\*.*" */ return( 1 ); } /* without wildcards maybe file or directory, need next check */ /* need add "\\*.*" if directory */ return( 0 ); } if( curr_ch == STRING( '*' ) ) break; if( curr_ch == STRING( '?' ) ) break; #if defined( __WIDECHAR__ ) || defined( __UNIX__ ) ++name; #else name = (char *)_mbsinc( (unsigned char *)name ); #endif } /* with wildcard must be file */ return( -1 ); }
static unsigned __GetTmpPath( char *buf ) { #ifndef __NETWARE__ static char *evars[] = { "TMP", "TEMP", "TMPDIR", "TEMPDIR", "" }; char **evar; char *tmp; #endif unsigned i; buf[0] = NULLCHAR; // initialize path #ifdef __NETWARE__ getcwd( buf, PATH_MAX ); // No environment vars on Netware #else for( evar = evars; **evar; ++evar ) { tmp = getenv( *evar ); if( (tmp != NULL) && (strlen( tmp ) <= PATH_MAX) ) { tmp = _fullpath( buf, tmp, PATH_MAX ); break; } } /* * If we didn't match on any environment vars, get current working dir */ if( buf[0] == NULLCHAR ) { getcwd( buf, PATH_MAX ); } #endif // if last char is not a path delimiter then append one i = strlen( buf ); if( i > 0 ) { if( !IS_DIR_SEP( buf[i - 1] ) ) { buf[i] = DIR_SEP; i++; buf[i] = NULLCHAR; } } return( i ); }
char *IoSuppIncPathElement( // GET ONE PATH ELEMENT FROM INCLUDE LIST const char *path, // - include list char *prefix ) // - buffer to store element { unsigned length; length = 0; for( ; ; ) { if( *path == '\0' ) break; if( (*path == INC_PATH_SEP) || (*path == ';') ) { ++path; if( length != 0 ) { break; } } else { ++length; *prefix++ = *path++; } } if( ( length > 1 ) && IS_DIR_SEP( *(prefix-1) ) ) --prefix; *prefix = '\0'; return( (char *)path ); }
char *GetPathElement( const char *path_list, const char *end, char **path ) { bool is_blank; char c; is_blank = TRUE; while( path_list != end && (c = *path_list) != '\0' ) { path_list++; if( IS_INCLUDE_LIST_SEP( c ) ) { if( !is_blank ) { break; } } else if( IS_DIR_SEP( c ) ) { is_blank = FALSE; *(*path)++ = DIR_SEP; } else if( !is_blank ) { *(*path)++ = c; } else if( c != ' ' ) { is_blank = FALSE; *(*path)++ = c; } } return( (char *)path_list ); }
_WCRTLINK void __F_NAME(_searchenv,_wsearchenv)( const CHAR_TYPE *name, const CHAR_TYPE *env_var, CHAR_TYPE *buffer ) { CHAR_TYPE *p, *p2; int prev_errno; size_t len; #ifdef __WIDECHAR__ if( _RWD_wenviron == NULL ) { __create_wide_environment(); } #endif prev_errno = _RWD_errno; if( __F_NAME(access,_waccess)( name, F_OK ) == 0 ) { p = buffer; len = 0; if( !IS_DIR_SEP( name[0] ) && name[0] != STRING( '.' ) ) { #ifndef __UNIX__ if( name[0] == NULLCHAR || name[1] != DRV_SEP ) { #endif __F_NAME(getcwd,_wgetcwd)( buffer, _MAX_PATH ); if( *buffer != NULLCHAR ) { len = __F_NAME(strlen,wcslen)( buffer ); p = buffer + len; if( p[-1] != DIR_SEP ) { if( len < ( _MAX_PATH - 1 ) ) { *p++ = DIR_SEP; len++; } } } #ifndef __UNIX__ } #endif } *p = NULLCHAR; __F_NAME(strncat,wcsncat)( p, name, ( _MAX_PATH - 1 ) - len ); return; } p = __F_NAME(getenv,_wgetenv)( env_var ); if( p != NULL ) { for( ;; ) { if( *p == NULLCHAR ) break; p2 = buffer; len = 0; while( *p != NULLCHAR ) { if( *p == LIST_SEPARATOR ) break; if( *p != STRING( '"' ) ) { if( len < ( _MAX_PATH - 1 ) ) { *p2++ = *p; len++; } } p++; } /* check for zero-length prefix which represents CWD */ if( p2 != buffer ) { #ifdef __UNIX__ if( !IS_DIR_SEP( p2[-1] ) ) { #else if( !IS_DIR_SEP( p2[-1] ) && p2[-1] != DRV_SEP ) { #endif if( len < (_MAX_PATH - 1) ) { *p2++ = DIR_SEP; len++; } } *p2 = NULLCHAR; len += __F_NAME(strlen,wcslen)( name ); if( len < _MAX_PATH ) { __F_NAME(strcat,wcscat)( p2, name ); /* check to see if file exists */ if( __F_NAME(access,_waccess)( buffer, 0 ) == 0 ) { _RWD_errno = prev_errno; return; } } } if( *p == NULLCHAR ) break; ++p; } } buffer[0] = NULLCHAR; }
/* Check that the WATCOM environment variable exists and if not, try to * heuristically determine what it should be and set it. Then check if * the PATH contains the appropriate paths and if not, add them depending * on the host platform. */ int watcom_setup_env( void ) { const char *watcom; char buf[FILENAME_MAX * 2]; int rc; size_t len; char *p; watcom = getenv( "WATCOM" ); /* If WATCOM env var isn't set, try to construct it */ if( watcom == NULL ) { char *path_sep = NULL; char *prev_path_sep = NULL; dbg_puts( "autoenv: WATCOM environment variable not found" ); if( _cmdname( buf ) == NULL ) { return( -1 ); } /* Set WATCOM to a directory one level up from the executable */ p = buf; while( *p != '\0' ) { if( IS_DIR_SEP( *p ) ) { if( path_sep != NULL ) { prev_path_sep = path_sep; } path_sep = p; } ++p; } if( prev_path_sep == NULL ) { return( -1 ); } /* Cut off path at next-to-last directory separator */ *prev_path_sep = '\0'; if( setenv( "WATCOM", buf, 0 ) != 0 ) { return( -1 ); } watcom = getenv( "WATCOM" ); dbg_puts( "autoenv: WATCOM environment successfully set:" ); dbg_puts( watcom ); } /* At this point, WATCOM is set; construct what we want in PATH */ len = strlen( watcom ); if( sizeof( buf ) < (2 * len + 16) ) { return( -2 ); } p = memcpy( buf, watcom, len ); p += len; *p++ = DIR_SEP; strcpy( p, PRIMARY_PATH ); #if defined( SECONDARY_PATH ) /* Add second path component on platforms that require it */ p += strlen( p ); *p++ = PATH_LIST_SEP; memcpy( p, watcom, len ); p += len; *p++ = DIR_SEP; strcpy( p, SECONDARY_PATH ); #endif /* Stick it in the PATH env var */ rc = add_path( "PATH", buf ); if( rc ) { return( rc ); } /* Finally set up platform specific stuff if applicable */ #ifdef HAVE_SETUP_OS_ENV return( setup_os_env( watcom ) ); #else return( 0 ); #endif }
int shell_cmd_is_allowed(const char *cmd, char **safecmd, char **cmdname) { char **p; char *buf; char *c, *d; const char *s; int pre; unsigned spaces; int allow = 0; /* pre == 1 means that the previous character is a white space pre == 0 means that the previous character is not a white space */ buf = xmalloc(strlen(cmd) + 1); strcpy(buf, cmd); c = buf; while (Isspace(*c)) c++; d = c; while (!Isspace(*d) && *d) d++; *d = '\0'; /* *cmdname is the first word of the command line. For example, *cmdname == "kpsewhich" for: \write18{kpsewhich --progname=dvipdfm --format="other text files" config} */ *cmdname = xstrdup(c); free(buf); /* Is *cmdname listed in a texmf.cnf vriable as shell_escape_commands = foo,bar,... ? */ p = cmdlist; if (p) { while (*p) { if (strcmp(*p, *cmdname) == 0) { /* *cmdname is found in the list, so restricted shell escape is allowed */ allow = 2; break; } p++; } } if (allow == 2) { spaces = 0; for (s = cmd; *s; s++) { if (Isspace(*s)) spaces++; } /* allocate enough memory (too much?) */ # ifdef WIN32 *safecmd = xmalloc(2 * strlen(cmd) + 3 + 2 * spaces); # else *safecmd = xmalloc(strlen(cmd) + 3 + 2 * spaces); # endif /* make a safe command line *safecmd */ s = cmd; while (Isspace(*s)) s++; d = *safecmd; while (!Isspace(*s) && *s) *d++ = *s++; pre = 1; while (*s) { /* Quotation given by a user. " should always be used; we transform it below. On Unix, if ' is used, simply immediately return a quotation error. */ if (*s == '\'') { return -1; } if (*s == '"') { /* All arguments are quoted as 'foo' (Unix) or "foo" (Windows) before calling system(). Therefore closing QUOTE is necessary if the previous character is not a white space. For example: --format="other text files" becomes '--format=''other text files' (Unix) "--format"="other text files" (Windows) */ if (pre == 0) { # ifdef WIN32 if (*(s-1) == '=') { *(d-1) = QUOTE; *d++ = '='; } else { *d++ = QUOTE; } # else *d++ = QUOTE; # endif } pre = 0; /* Output the quotation mark for the quoted argument. */ *d++ = QUOTE; s++; while (*s != '"') { /* Illegal use of ', or closing quotation mark is missing */ if (*s == '\'' || *s == '\0') return -1; # if 0 # ifdef WIN32 if (char_needs_quote(*s)) *d++ = '^'; # endif # endif *d++ = *s++; } /* Closing quotation mark will be output afterwards, so we do nothing here. */ s++; /* The character after the closing quotation mark should be a white space or NULL. */ if (!Isspace(*s) && *s) return -1; /* Beginning of a usual argument. */ } else if (pre == 1 && !Isspace(*s)) { pre = 0; *d++ = QUOTE; # if 0 # ifdef WIN32 if (char_needs_quote(*s)) *d++ = '^'; # endif # endif *d++ = *s++; /* Ending of a usual argument. */ } else if (pre == 0 && Isspace(*s)) { pre = 1; /* Closing quotation mark */ *d++ = QUOTE; *d++ = *s++; } else { /* Copy a character from cmd to *safecmd. */ # if 0 # ifdef WIN32 if (char_needs_quote(*s)) *d++ = '^'; # endif # endif *d++ = *s++; } } /* End of the command line. */ if (pre == 0) { *d++ = QUOTE; } *d = '\0'; #ifdef WIN32 { char *p, *q, *r; p = *safecmd; if (strlen (p) > 2 && p[1] == ':' && !IS_DIR_SEP (p[2])) { q = xmalloc (strlen (p) + 2); q[0] = p[0]; q[1] = p[1]; q[2] = '/'; q[3] = '\0'; strcat (q, (p + 2)); free (*safecmd); *safecmd = q; } else if (!IS_DIR_SEP (p[0]) && !(p[1] == ':' && IS_DIR_SEP (p[2]))) { p = kpse_var_value ("SELFAUTOLOC"); if (p) { r = *safecmd; while (*r && !Isspace(*r)) r++; if (*r == '\0') q = concatn ("\"", p, "/", *safecmd, "\"", NULL); else { *r = '\0'; r++; while (*r && Isspace(*r)) r++; if (*r) q = concatn ("\"", p, "/", *safecmd, "\" ", r, NULL); else q = concatn ("\"", p, "/", *safecmd, "\"", NULL); } free (p); free (*safecmd); *safecmd = q; } } } #endif } return allow; }
/*********************************************************************** * hb_bd_title_scan **********************************************************************/ hb_title_t * hb_bd_title_scan( hb_bd_t * d, int tt, uint64_t min_duration ) { hb_title_t * title; hb_chapter_t * chapter; int ii, jj; BLURAY_TITLE_INFO * ti = NULL; hb_log( "bd: scanning title %d", tt ); title = hb_title_init( d->path, tt ); title->demuxer = HB_TS_DEMUXER; title->type = HB_BD_TYPE; title->reg_desc = STR4_TO_UINT32("HDMV"); char * p_cur, * p_last = d->path; for( p_cur = d->path; *p_cur; p_cur++ ) { if( IS_DIR_SEP(p_cur[0]) && p_cur[1] ) { p_last = &p_cur[1]; } } snprintf( title->name, sizeof( title->name ), "%s", p_last ); char *dot_term = strrchr(title->name, '.'); if (dot_term) *dot_term = '\0'; title->vts = 0; title->ttn = 0; if (tt <= d->title_count) { ti = d->title_info[tt - 1]; } if ( ti == NULL ) { hb_log( "bd: invalid title" ); goto fail; } if ( ti->clip_count == 0 ) { hb_log( "bd: stream has no clips" ); goto fail; } if ( ti->clips[0].video_stream_count == 0 ) { hb_log( "bd: stream has no video" ); goto fail; } hb_log( "bd: playlist %05d.MPLS", ti->playlist ); title->playlist = ti->playlist; uint64_t pkt_count = 0; for ( ii = 0; ii < ti->clip_count; ii++ ) { pkt_count += ti->clips[ii].pkt_count; } title->block_start = 0; title->block_end = pkt_count; title->block_count = pkt_count; title->angle_count = ti->angle_count; /* Get duration */ title->duration = ti->duration; title->hours = title->duration / 90000 / 3600; title->minutes = ( ( title->duration / 90000 ) % 3600 ) / 60; title->seconds = ( title->duration / 90000 ) % 60; hb_log( "bd: duration is %02d:%02d:%02d (%"PRIu64" ms)", title->hours, title->minutes, title->seconds, title->duration / 90 ); /* ignore short titles because they're often stills */ if( ti->duration < min_duration ) { hb_log( "bd: ignoring title (too short)" ); goto fail; } if (global_verbosity_level >= 2) { show_clip_list(ti); } BLURAY_STREAM_INFO * bdvideo = &ti->clips[0].video_streams[0]; title->video_id = bdvideo->pid; title->video_stream_type = bdvideo->coding_type; hb_log( "bd: video id=0x%x, stream type=%s, format %s", title->video_id, bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_MPEG1 ? "MPEG1" : bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_MPEG2 ? "MPEG2" : bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_VC1 ? "VC-1" : bdvideo->coding_type == BLURAY_STREAM_TYPE_VIDEO_H264 ? "H.264" : "Unknown", bdvideo->format == BLURAY_VIDEO_FORMAT_480I ? "480i" : bdvideo->format == BLURAY_VIDEO_FORMAT_576I ? "576i" : bdvideo->format == BLURAY_VIDEO_FORMAT_480P ? "480p" : bdvideo->format == BLURAY_VIDEO_FORMAT_1080I ? "1080i" : bdvideo->format == BLURAY_VIDEO_FORMAT_720P ? "720p" : bdvideo->format == BLURAY_VIDEO_FORMAT_1080P ? "1080p" : bdvideo->format == BLURAY_VIDEO_FORMAT_576P ? "576p" : "Unknown" ); switch( bdvideo->coding_type ) { case BLURAY_STREAM_TYPE_VIDEO_MPEG1: case BLURAY_STREAM_TYPE_VIDEO_MPEG2: title->video_codec = WORK_DECAVCODECV; title->video_codec_param = AV_CODEC_ID_MPEG2VIDEO; break; case BLURAY_STREAM_TYPE_VIDEO_VC1: title->video_codec = WORK_DECAVCODECV; title->video_codec_param = AV_CODEC_ID_VC1; break; case BLURAY_STREAM_TYPE_VIDEO_H264: title->video_codec = WORK_DECAVCODECV; title->video_codec_param = AV_CODEC_ID_H264; break; default: hb_log( "scan: unknown video codec (0x%x)", bdvideo->coding_type ); goto fail; } switch ( bdvideo->aspect ) { case BLURAY_ASPECT_RATIO_4_3: title->container_dar.num = 4; title->container_dar.den = 3; break; case BLURAY_ASPECT_RATIO_16_9: title->container_dar.num = 16; title->container_dar.den = 9; break; default: hb_log( "bd: unknown aspect" ); goto fail; } hb_log("bd: aspect = %d:%d", title->container_dar.num, title->container_dar.den); /* Detect audio */ // Max primary BD audios is 32 int matches; int most_audio = 0; int audio_clip_index = 0; if (ti->clip_count > 2) { // All BD clips are not all required to have the same audio. // But clips that have seamless transition are required // to have the same audio as the previous clip. // So find the clip that has the most other clips with the // matching audio. for ( ii = 0; ii < ti->clip_count; ii++ ) { matches = 0; for ( jj = 0; jj < ti->clip_count; jj++ ) { if ( bd_audio_equal( &ti->clips[ii], &ti->clips[jj] ) ) { matches++; } } if ( matches > most_audio ) { most_audio = matches; audio_clip_index = ii; } } } else if (ti->clip_count == 2) { // If there are only 2 clips, pick audios from the longer clip if (ti->clips[0].pkt_count < ti->clips[1].pkt_count) audio_clip_index = 1; } // Add all the audios found in the above clip. for (ii = 0; ii < ti->clips[audio_clip_index].audio_stream_count; ii++) { BLURAY_STREAM_INFO * bdaudio; bdaudio = &ti->clips[audio_clip_index].audio_streams[ii]; switch (bdaudio->coding_type) { case BLURAY_STREAM_TYPE_AUDIO_TRUHD: // Add 2 audio tracks. One for TrueHD and one for AC-3 add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_AC3, HB_ACODEC_AC3, AV_CODEC_ID_AC3); add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_TRUEHD, HB_ACODEC_FFTRUEHD, AV_CODEC_ID_TRUEHD); break; case BLURAY_STREAM_TYPE_AUDIO_DTS: add_audio(ii, title->list_audio, bdaudio, 0, HB_ACODEC_DCA, AV_CODEC_ID_DTS); break; case BLURAY_STREAM_TYPE_AUDIO_MPEG2: case BLURAY_STREAM_TYPE_AUDIO_MPEG1: add_audio(ii, title->list_audio, bdaudio, 0, HB_ACODEC_FFMPEG, AV_CODEC_ID_MP2); break; case BLURAY_STREAM_TYPE_AUDIO_AC3PLUS: add_audio(ii, title->list_audio, bdaudio, 0, HB_ACODEC_FFEAC3, AV_CODEC_ID_EAC3); break; case BLURAY_STREAM_TYPE_AUDIO_LPCM: add_audio(ii, title->list_audio, bdaudio, 0, HB_ACODEC_FFMPEG, AV_CODEC_ID_PCM_BLURAY); break; case BLURAY_STREAM_TYPE_AUDIO_AC3: add_audio(ii, title->list_audio, bdaudio, 0, HB_ACODEC_AC3, AV_CODEC_ID_AC3); break; case BLURAY_STREAM_TYPE_AUDIO_DTSHD_MASTER: case BLURAY_STREAM_TYPE_AUDIO_DTSHD: // Add 2 audio tracks. One for DTS-HD and one for DTS add_audio(ii, title->list_audio, bdaudio, HB_SUBSTREAM_BD_DTS, HB_ACODEC_DCA, AV_CODEC_ID_DTS); // DTS-HD is special. The substreams must be concatinated // DTS-core followed by DTS-hd-extensions. Setting // a substream id of 0 says use all substreams. add_audio(ii, title->list_audio, bdaudio, 0, HB_ACODEC_DCA_HD, AV_CODEC_ID_DTS); break; default: hb_log("scan: unknown audio pid 0x%x codec 0x%x", bdaudio->pid, bdaudio->coding_type); break; } } // Add all the subtitles found in the above clip. for ( ii = 0; ii < ti->clips[audio_clip_index].pg_stream_count; ii++ ) { BLURAY_STREAM_INFO * bdpgs; bdpgs = &ti->clips[audio_clip_index].pg_streams[ii]; switch( bdpgs->coding_type ) { case BLURAY_STREAM_TYPE_SUB_PG: add_subtitle(ii, title->list_subtitle, bdpgs, WORK_DECPGSSUB); break; default: hb_log( "scan: unknown subtitle pid 0x%x codec 0x%x", bdpgs->pid, bdpgs->coding_type ); break; } } /* Chapters */ for ( ii = 0, jj = 0; ii < ti->chapter_count; ii++ ) { char chapter_title[80]; // Sanity check start time of this chapter. // If it is beyond the end of the title, drop it. if (ti->chapters[ii].start > ti->duration) { hb_log("bd: chapter %d invalid start %"PRIu64", dropping", ii+1, ti->chapters[ii].start); continue; } chapter = calloc( sizeof( hb_chapter_t ), 1 ); chapter->index = ++jj; sprintf( chapter_title, "Chapter %d", chapter->index ); hb_chapter_set_title( chapter, chapter_title ); chapter->duration = ti->chapters[ii].duration; chapter->block_start = ti->chapters[ii].offset; // Sanity check chapter duration and start times // Have seen some invalid durations in the wild if (ii < ti->chapter_count - 1) { // Validate start time if (ti->chapters[ii+1].start < ti->chapters[ii].start) { hb_log("bd: chapter %d invalid start %"PRIu64"", ii+1, ti->chapters[ii+1].start); ti->chapters[ii+1].start = ti->chapters[ii].start + chapter->duration; } if (ti->chapters[ii+1].start - ti->chapters[ii].start != chapter->duration) { hb_log("bd: chapter %d invalid duration %"PRIu64"", ii+1, chapter->duration); chapter->duration = ti->chapters[ii+1].start - ti->chapters[ii].start; } } else { if (ti->duration - ti->chapters[ii].start != chapter->duration) { hb_log("bd: chapter %d invalid duration %"PRIu64"", ii+1, chapter->duration); chapter->duration = ti->duration - ti->chapters[ii].start; } } int seconds = ( chapter->duration + 45000 ) / 90000; chapter->hours = ( seconds / 3600 ); chapter->minutes = ( seconds % 3600 ) / 60; chapter->seconds = ( seconds % 60 ); hb_log( "bd: chap %d packet=%"PRIu64", %"PRIu64" ms", chapter->index, chapter->block_start, chapter->duration / 90 ); hb_list_add( title->list_chapter, chapter ); } hb_log( "bd: title %d has %d chapters", tt, ti->chapter_count ); /* This title is ok so far */ goto cleanup; fail: hb_title_close( &title ); cleanup: return title; }
static string remove_dots P1C(string, dir) { #ifdef AMIGA return dir; #else string c; unsigned len; string ret = (string) ""; /* We always reassign. */ for (c = kpse_filename_component (dir); c; c = kpse_filename_component (NULL)) { if (STREQ (c, ".")) { /* If leading ., replace with cwd. Else ignore. */ if (*ret == 0) { ret = xgetcwd (); } } else if (STREQ (c, "..")) { /* If leading .., start with xdirname (cwd). Else remove last component from ret, if any. */ if (*ret == 0) { string dot = xgetcwd (); ret = xdirname (dot); free (dot); } else { unsigned last; for (last = strlen (ret); last > (NAME_BEGINS_WITH_DEVICE (ret) ? 2 : 0); last--) { if (IS_DIR_SEP (ret[last - 1])) { /* If we have `/../', that's the same as `/'. */ if (last > 1) { ret[last - 1] = 0; } break; } } } } else { /* Not . or ..; just append. Include a directory separator unless our string already ends with one. This also changes all directory separators into the canonical DIR_SEP_STRING. */ string temp; len = strlen (ret); temp = concat3 (ret, ((len > 0 && ret[len - 1] == DIR_SEP) || (NAME_BEGINS_WITH_DEVICE (c) && *ret == 0)) ? "" : DIR_SEP_STRING, c); if (*ret) free (ret); ret = temp; } } /* Remove a trailing /, just in case it snuck in. */ len = strlen (ret); if (len > 0 && ret[len - 1] == DIR_SEP) { ret[len - 1] = 0; } return ret; #endif /* not AMIGA */ }
string xdirname (const_string name) { string ret; unsigned limit = 0, loc; #if defined(WIN32) string p; unsigned i, j; #endif /* Ignore a NULL name. */ if (!name) return NULL; if (NAME_BEGINS_WITH_DEVICE(name)) { limit = 2; } else if (IS_UNC_NAME(name)) { for (limit = 2; name[limit] && !IS_DIR_SEP (name[limit]); limit++) #if defined(WIN32) && defined(KPSE_COMPAT_API) if (IS_KANJI(name+limit)) limit++ #endif ; if (name[limit++] && name[limit] && !IS_DIR_SEP (name[limit])) { for (; name[limit] && !IS_DIR_SEP (name[limit]); limit++) #if defined(WIN32) && defined(KPSE_COMPAT_API) if (IS_KANJI(name+limit)) limit++ #endif ; limit--; } else /* malformed UNC name, backup */ limit = 0; } #if defined(WIN32) j = loc = limit; if (j > 2) j++; for (i = j; name[i]; i++) { if (IS_DIR_SEP (name[i])) { j = i; for (i++; IS_DIR_SEP (name[i]); i++) ; loc = i + 1; } #if defined (KPSE_COMPAT_API) else if (IS_KANJI(name+i)) i++; #endif } #else for (loc = strlen (name); loc > limit && !IS_DIR_SEP (name[loc-1]); loc--) ; #endif if (loc == limit) { if (limit == 0) ret = xstrdup ("."); else if (limit == 2) { ret = (string)xmalloc(4); ret[0] = name[0]; ret[1] = name[1]; ret[2] = '.'; ret[3] = '\0'; } else { /* UNC name is "//server/share". */ ret = xstrdup (name); } } else { /* If have ///a, must return /, so don't strip off everything. */ #if defined(WIN32) loc = j; if (loc == limit && IS_DIR_SEP (name[loc])) loc++; #else while (loc > limit+1 && IS_DIR_SEP (name[loc-1])) { loc--; } #endif ret = (string)xmalloc(loc+1); strncpy(ret, name, loc); ret[loc] = '\0'; } #if defined(WIN32) for (p = ret; *p; p++) { if (*p == '\\') *p = '/'; #if defined (KPSE_COMPAT_API) else if (IS_KANJI(p)) p++; #endif } #endif return ret; }
string kpathsea_tilde_expand (kpathsea kpse, string name) { string expansion; const_string home; const_string prefix; #if defined(WIN32) string p; #endif (void)kpse; /* currenty not used */ assert (name); /* If there is a leading "!!", set prefix to "!!", otherwise use the empty string. After this, we can test whether a prefix was found by checking *prefix, and it is safe to unconditionally prepend it. */ if (name[0] == '!' && name[1] == '!') { name += 2; prefix = "!!"; } else { prefix = ""; } /* If no leading tilde, do nothing, and return the original string. */ if (*name != '~' #ifndef USE_GETPWNAM /* Same for `~user' or `~user/', but no passwd database. */ || (name[1] && !IS_DIR_SEP (name[1])) #endif ) { if (*prefix) name -= 2; expansion = name; } else { /* If a bare tilde, return the home directory or `.'; if just `~user', return that user's home directory or `.'. Very unlikely that the directory name will do anyone any good, but ... */ unsigned c; #ifdef USE_GETPWNAM /* If `~user' or `~user/', look up user in the passwd database. */ if (name[1] && !IS_DIR_SEP (name[1])) { struct passwd *p; string user; c = 2; while (!IS_DIR_SEP (name[c]) && name[c] != 0) { /* find user name */ #if defined(WIN32) if (kpathsea_IS_KANJI(kpse, name+c)) c++; #endif c++; } user = (string) xmalloc (c); strncpy (user, name + 1, c - 1); user[c - 1] = 0; #if defined(WIN32) && !defined(__MINGW32__) p = kpathsea_getpwnam (kpse, user); #else /* We only need the cast here for (deficient) systems which do not declare `getpwnam' in <pwd.h>. */ p = (struct passwd *) getpwnam (user); #endif free (user); /* If no such user, just use `.'. */ home = p ? p->pw_dir : "."; } else #endif /* USE_GETPWNAM */ { c = 1; home = getenv (HOMEVAR); if (!home) home = "."; } /* handle leading // */ if (IS_DIR_SEP (*home) && IS_DIR_SEP (home[1])) home++; /* If HOME ends in /, omit the / in ~/ or ~user/. */ if (name[c]) { #if defined(WIN32) const_string q; for (q = home; *q; q++) { if (IS_DIR_SEP (*q) && q[1] == 0) c++; else if (kpathsea_IS_KANJI(kpse, q)) q++; } #else if (IS_DIR_SEP (home[strlen (home) - 1])) c++; #endif } expansion = concat3 (prefix, home, name + c); } #if defined(WIN32) for (p = expansion; *p; p++) { if (*p == '\\') *p = '/'; else if (kpathsea_IS_KANJI(kpse, p)) p++; } #endif /* We may return the same thing as the original, and then we might not be returning a malloc-ed string. Callers beware. Sorry. */ return expansion; }
string kpathsea_make_tex (kpathsea kpse, kpse_file_format_type format, const_string base) { kpse_format_info_type spec; /* some compilers lack struct initialization */ string ret = NULL; spec = kpse->format_info[format]; if (!spec.type) { /* Not initialized yet? */ kpathsea_init_format (kpse, format); spec = kpse->format_info[format]; } if (spec.program && spec.program_enabled_p) { /* See the documentation for the envvars we're dealing with here. */ /* Number of arguments is spec.argc + 1, plus the trailing NULL. */ string *args = XTALLOC (spec.argc + 2, string); /* Helpers */ int argnum; int i; /* FIXME * Check whether the name we were given is likely to be a problem. * Right now we err on the side of strictness: * - may not start with a hyphen (fixable in the scripts). * - allowed are: alphanumeric, underscore, hyphen, period, plus * ? also allowed DIRSEP, as we can be fed that when creating pk fonts * No doubt some possibilities were overlooked. */ if (base[0] == '-' /* || IS_DIR_SEP(base[0]) */) { fprintf(stderr, "kpathsea:make_tex: Invalid filename `%s', starts with '%c'\n", base, base[0]); return NULL; } for (i = 0; base[i]; i++) { if (!ISALNUM(base[i]) && base[i] != '-' && base[i] != '+' && base[i] != '_' && base[i] != '.' && !IS_DIR_SEP(base[i])) { fprintf(stderr, "kpathsea:make_tex: Invalid filename `%s', contains '%c'\n", base, base[i]); return NULL; } } if (format == kpse_gf_format || format == kpse_pk_format || format == kpse_any_glyph_format) set_maketex_mag (kpse); /* Here's an awful kludge: if the mode is `/', mktexpk recognizes it as a special case. `kpse_prog_init' sets it to this in the first place when no mode is otherwise specified; this is so when the user defines a resolution, they don't also have to specify a mode; instead, mktexpk's guesses will take over. They use / for the value because then when it is expanded as part of the PKFONTS et al. path values, we'll wind up searching all the pk directories. We put $MAKETEX_MODE in the path values in the first place so that sites with two different devices with the same resolution can find the right fonts; but such sites are uncommon, so they shouldn't make things harder for everyone else. */ for (argnum = 0; argnum < spec.argc; argnum++) { args[argnum] = kpathsea_var_expand (kpse, spec.argv[argnum]); } args[argnum++] = xstrdup(base); args[argnum] = NULL; ret = maketex (kpse, format, args); for (argnum = 0; args[argnum] != NULL; argnum++) free (args[argnum]); free (args); } return ret; }
/* * Actually do a base backup for the specified tablespaces. * * This is split out mainly to avoid complaints about "variable might be * clobbered by longjmp" from stupider versions of gcc. */ static void perform_base_backup(basebackup_options *opt, DIR *tblspcdir) { XLogRecPtr startptr; TimeLineID starttli; XLogRecPtr endptr; TimeLineID endtli; char *labelfile; int datadirpathlen; datadirpathlen = strlen(DataDir); backup_started_in_recovery = RecoveryInProgress(); startptr = do_pg_start_backup(opt->label, opt->fastcheckpoint, &starttli, &labelfile); /* * Once do_pg_start_backup has been called, ensure that any failure causes * us to abort the backup so we don't "leak" a backup counter. For this reason, * *all* functionality between do_pg_start_backup() and do_pg_stop_backup() * should be inside the error cleanup block! */ PG_ENSURE_ERROR_CLEANUP(base_backup_cleanup, (Datum) 0); { List *tablespaces = NIL; ListCell *lc; struct dirent *de; tablespaceinfo *ti; SendXlogRecPtrResult(startptr, starttli); /* * Calculate the relative path of temporary statistics directory in order * to skip the files which are located in that directory later. */ if (is_absolute_path(pgstat_stat_directory) && strncmp(pgstat_stat_directory, DataDir, datadirpathlen) == 0) statrelpath = psprintf("./%s", pgstat_stat_directory + datadirpathlen + 1); else if (strncmp(pgstat_stat_directory, "./", 2) != 0) statrelpath = psprintf("./%s", pgstat_stat_directory); else statrelpath = pgstat_stat_directory; /* Collect information about all tablespaces */ while ((de = ReadDir(tblspcdir, "pg_tblspc")) != NULL) { char fullpath[MAXPGPATH]; char linkpath[MAXPGPATH]; char *relpath = NULL; int rllen; /* Skip special stuff */ if (strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; snprintf(fullpath, sizeof(fullpath), "pg_tblspc/%s", de->d_name); #if defined(HAVE_READLINK) || defined(WIN32) rllen = readlink(fullpath, linkpath, sizeof(linkpath)); if (rllen < 0) { ereport(WARNING, (errmsg("could not read symbolic link \"%s\": %m", fullpath))); continue; } else if (rllen >= sizeof(linkpath)) { ereport(WARNING, (errmsg("symbolic link \"%s\" target is too long", fullpath))); continue; } linkpath[rllen] = '\0'; /* * Relpath holds the relative path of the tablespace directory * when it's located within PGDATA, or NULL if it's located * elsewhere. */ if (rllen > datadirpathlen && strncmp(linkpath, DataDir, datadirpathlen) == 0 && IS_DIR_SEP(linkpath[datadirpathlen])) relpath = linkpath + datadirpathlen + 1; ti = palloc(sizeof(tablespaceinfo)); ti->oid = pstrdup(de->d_name); ti->path = pstrdup(linkpath); ti->rpath = relpath ? pstrdup(relpath) : NULL; ti->size = opt->progress ? sendTablespace(fullpath, true) : -1; tablespaces = lappend(tablespaces, ti); #else /* * If the platform does not have symbolic links, it should not be * possible to have tablespaces - clearly somebody else created * them. Warn about it and ignore. */ ereport(WARNING, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("tablespaces are not supported on this platform"))); #endif } /* Add a node for the base directory at the end */ ti = palloc0(sizeof(tablespaceinfo)); ti->size = opt->progress ? sendDir(".", 1, true, tablespaces) : -1; tablespaces = lappend(tablespaces, ti); /* Send tablespace header */ SendBackupHeader(tablespaces); /* Setup and activate network throttling, if client requested it */ if (opt->maxrate > 0) { throttling_sample = (int64) opt->maxrate * (int64) 1024 / THROTTLING_FREQUENCY; /* * The minimum amount of time for throttling_sample bytes to be * transfered. */ elapsed_min_unit = USECS_PER_SEC / THROTTLING_FREQUENCY; /* Enable throttling. */ throttling_counter = 0; /* The 'real data' starts now (header was ignored). */ throttled_last = GetCurrentIntegerTimestamp(); } else { /* Disable throttling. */ throttling_counter = -1; } /* Send off our tablespaces one by one */ foreach(lc, tablespaces) { tablespaceinfo *ti = (tablespaceinfo *) lfirst(lc); StringInfoData buf; /* Send CopyOutResponse message */ pq_beginmessage(&buf, 'H'); pq_sendbyte(&buf, 0); /* overall format */ pq_sendint(&buf, 0, 2); /* natts */ pq_endmessage(&buf); if (ti->path == NULL) { struct stat statbuf; /* In the main tar, include the backup_label first... */ sendFileWithContent(BACKUP_LABEL_FILE, labelfile); /* ... then the bulk of the files ... */ sendDir(".", 1, false, tablespaces); /* ... and pg_control after everything else. */ if (lstat(XLOG_CONTROL_FILE, &statbuf) != 0) ereport(ERROR, (errcode_for_file_access(), errmsg("could not stat control file \"%s\": %m", XLOG_CONTROL_FILE))); sendFile(XLOG_CONTROL_FILE, XLOG_CONTROL_FILE, &statbuf, false); } else sendTablespace(ti->path, false); /* * If we're including WAL, and this is the main data directory we * don't terminate the tar stream here. Instead, we will append * the xlog files below and terminate it then. This is safe since * the main data directory is always sent *last*. */ if (opt->includewal && ti->path == NULL) { Assert(lnext(lc) == NULL); } else pq_putemptymessage('c'); /* CopyDone */ } }
static void do_subdir P4C(str_llist_type *, str_list_ptr, const_string, elt, unsigned, elt_length, const_string, post) { #ifdef WIN32 WIN32_FIND_DATA find_file_data; HANDLE hnd; int proceed; #else DIR *dir; struct dirent *e; #endif /* not WIN32 */ fn_type name; /* Some old compilers don't allow aggregate initialization. */ name = fn_copy0 (elt, elt_length); assert (IS_DIR_SEP (elt[elt_length - 1]) || IS_DEVICE_SEP (elt[elt_length - 1])); #if defined (WIN32) strcpy(dirname, FN_STRING(name)); strcat(dirname, "/*.*"); /* "*.*" or "*" -- seems equivalent. */ hnd = FindFirstFile(dirname, &find_file_data); if (hnd == INVALID_HANDLE_VALUE) { fn_free(&name); return; } /* Include top level before subdirectories, if nothing to match. */ if (*post == 0) dir_list_add (str_list_ptr, FN_STRING (name)); else { /* If we do have something to match, see if it exists. For example, POST might be `pk/ljfour', and they might have a directory `$TEXMF/fonts/pk/ljfour' that we should find. */ fn_str_grow (&name, post); expand_elt (str_list_ptr, FN_STRING (name), elt_length); fn_shrink_to (&name, elt_length); } proceed = 1; while (proceed) { if (find_file_data.cFileName[0] != '.') { /* Construct the potential subdirectory name. */ fn_str_grow (&name, find_file_data.cFileName); if (find_file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { unsigned potential_len = FN_LENGTH (name); /* It's a directory, so append the separator. */ fn_str_grow (&name, DIR_SEP_STRING); do_subdir (str_list_ptr, FN_STRING (name), potential_len, post); } fn_shrink_to (&name, elt_length); } proceed = FindNextFile (hnd, &find_file_data); } fn_free (&name); FindClose(hnd); #else /* not WIN32 */ /* If we can't open it, quit. */ dir = opendir (FN_STRING (name)); if (dir == NULL) { fn_free (&name); return; } /* Include top level before subdirectories, if nothing to match. */ if (*post == 0) dir_list_add (str_list_ptr, FN_STRING (name)); else { /* If we do have something to match, see if it exists. For example, POST might be `pk/ljfour', and they might have a directory `$TEXMF/fonts/pk/ljfour' that we should find. */ fn_str_grow (&name, post); expand_elt (str_list_ptr, FN_STRING (name), elt_length); fn_shrink_to (&name, elt_length); } while ((e = readdir (dir)) != NULL) { /* If it begins with a `.', never mind. (This allows ``hidden'' directories that the algorithm won't find.) */ if (e->d_name[0] != '.') { int links; /* Construct the potential subdirectory name. */ fn_str_grow (&name, e->d_name); /* If we can't stat it, or if it isn't a directory, continue. */ links = dir_links (FN_STRING (name)); if (links >= 0) { unsigned potential_len = FN_LENGTH (name); /* It's a directory, so append the separator. */ fn_str_grow (&name, DIR_SEP_STRING); /* Should we recurse? To see if the subdirectory is a leaf, check if it has two links (one for . and one for ..). This means that symbolic links to directories do not affect the leaf-ness. This is arguably wrong, but the only alternative I know of is to stat every entry in the directory, and that is unacceptably slow. The #ifdef here makes all this configurable at compile-time, so that if we're using VMS directories or some such, we can still find subdirectories, even if it is much slower. */ #ifdef ST_NLINK_TRICK #ifdef AMIGA /* With SAS/C++ 6.55 on the Amiga, `stat' sets the `st_nlink' field to -1 for a file, or to 1 for a directory. */ if (links == 1) #else if (links > 2) #endif /* not AMIGA */ #endif /* not ST_NLINK_TRICK */ /* All criteria are met; find subdirectories. */ do_subdir (str_list_ptr, FN_STRING (name), potential_len, post); #ifdef ST_NLINK_TRICK else if (*post == 0) /* Nothing to match, no recursive subdirectories to look for: we're done with this branch. Add it. */ dir_list_add (str_list_ptr, FN_STRING (name)); #endif } /* Remove the directory entry we just checked from `name'. */ fn_shrink_to (&name, elt_length); } } fn_free (&name); xclosedir (dir); #endif /* not WIN32 */ }
void kpse_set_program_name P2C(const_string, argv0, const_string, progname) { string ext, sdir, sdir_parent, sdir_grandparent; string s = getenv ("KPATHSEA_DEBUG"); #ifdef WIN32 string debug_output = getenv("KPATHSEA_DEBUG_OUTPUT"); string append_debug_output = getenv("KPATHSEA_DEBUG_APPEND"); int err, olderr; #endif /* Set debugging stuff first, in case we end up doing debuggable stuff during this initialization. */ if (s) { kpathsea_debug |= atoi (s); } #ifndef HAVE_PROGRAM_INVOCATION_NAME #if defined(WIN32) /* Set various info about user. Among many things, ensure that HOME is set. If debug_paths is on, turn on some message if $HOME is not found. */ if (KPSE_DEBUG_P(KPSE_DEBUG_PATHS)) { set_home_warning(); } init_user_info(); /* redirect stderr to debug_output. Easier to send logfiles. */ if (debug_output) { int flags = _O_CREAT | _O_TRUNC | _O_RDWR; err = -1; if (_stricmp(debug_output, "con") == 0 || _stricmp(debug_output, "con:") == 0) { err = _fileno(stdout); } else { if (append_debug_output) { flags = _O_CREAT | _O_APPEND | _O_WRONLY; } else { flags = _O_CREAT | _O_TRUNC | _O_WRONLY; xputenv("KPATHSEA_DEBUG_APPEND", "yes"); } } if ((err < 0) && (err = _open(debug_output, flags, _S_IREAD | _S_IWRITE)) == -1) { WARNING1("Can't open %s for stderr redirection!\n", debug_output); perror(debug_output); } else if ((olderr = _dup(fileno(stderr))) == -1) { WARNING("Can't dup() stderr!\n"); close(err); } else if (_dup2(err, fileno(stderr)) == -1) { WARNING1("Can't redirect stderr to %s!\n", debug_output); close(olderr); close(err); } else { close(err); } } /* Win95 always gives the short filename for argv0, not the long one. There is only this way to catch it. It makes all the selfdir stuff useless for win32. */ { char short_path[PATH_MAX], path[PATH_MAX], *fp; /* SearchPath() always gives back an absolute directory */ if (SearchPath(NULL, argv0, ".exe", PATH_MAX, short_path, &fp) == 0) FATAL1("Can't determine where the executable %s is.\n", argv0); if (!win32_get_long_filename(short_path, path, sizeof(path))) { FATAL1("This path points to an invalid file : %s\n", short_path); } /* slashify the dirname */ for (fp = path; fp && *fp; fp++) if (IS_DIR_SEP(*fp)) *fp = DIR_SEP; /* sdir will be the directory of the executable, ie: c:/TeX/bin */ sdir = xdirname(path); program_invocation_name = xstrdup(xbasename(path)); } #elif defined(__DJGPP__) /* DJGPP programs support long filenames on Windows 95, but ARGV0 there is always made with the short 8+3 aliases of all the pathname elements. If long names are supported, we need to convert that to a long name. All we really need is to call `_truename', but most of the code below is required to deal with the special case of networked drives. */ if (pathconf (argv0, _PC_NAME_MAX) > 12) { char long_progname[PATH_MAX]; if (_truename (argv0, long_progname)) { char *fp; if (long_progname[1] != ':') { /* A complication: `_truename' returns network-specific string at the beginning of `long_progname' when the program resides on a networked drive, and DOS calls cannot grok such pathnames. We need to convert the filesystem name back to a drive letter. */ char rootname[PATH_MAX], rootdir[4]; if (argv0[0] && argv0[1] == ':') rootdir[0] = argv0[0]; /* explicit drive in `argv0' */ else rootdir[0] = getdisk () + 'A'; rootdir[1] = ':'; rootdir[2] = '\\'; rootdir[3] = '\0'; if (_truename (rootdir, rootname)) { /* Find out where `rootname' ends in `long_progname' and replace it with the drive letter. */ int root_len = strlen (rootname); if (IS_DIR_SEP (rootname[root_len - 1])) root_len--; /* keep the trailing slash */ long_progname[0] = rootdir[0]; long_progname[1] = ':'; memmove (long_progname + 2, long_progname + root_len, strlen (long_progname + root_len) + 1); } } /* Convert everything to canonical form. */ if (long_progname[0] >= 'A' && long_progname[0] <= 'Z') long_progname[0] += 'a' - 'A'; /* make drive lower case, for beauty */ for (fp = long_progname; *fp; fp++) if (IS_DIR_SEP (*fp)) *fp = DIR_SEP; program_invocation_name = xstrdup (long_progname); } else /* If `_truename' failed, God help them, because we won't... */ program_invocation_name = xstrdup (argv0); } else program_invocation_name = xstrdup (argv0); #else /* !WIN32 && !__DJGPP__ */ program_invocation_name = xstrdup (argv0); #endif #endif /* not HAVE_PROGRAM_INVOCATION_NAME */ /* We need to find SELFAUTOLOC *before* removing the ".exe" suffix from the program_name, otherwise the PATH search inside selfdir will fail, since `prog' doesn't exists as a file, there's `prog.exe' instead. */ #ifndef WIN32 sdir = selfdir (program_invocation_name); #endif /* SELFAUTODIR is actually the parent of the invocation directory, and SELFAUTOPARENT the grandparent. This is how teTeX did it. */ xputenv ("SELFAUTOLOC", sdir); sdir_parent = xdirname (sdir); xputenv ("SELFAUTODIR", sdir_parent); sdir_grandparent = xdirname (sdir_parent); xputenv ("SELFAUTOPARENT", sdir_grandparent); free (sdir); free (sdir_parent); free (sdir_grandparent); #ifndef HAVE_PROGRAM_INVOCATION_NAME program_invocation_short_name = (string)xbasename (program_invocation_name); #endif if (progname) { kpse_program_name = xstrdup (progname); } else { /* If configured --enable-shared and running from the build directory with the wrapper scripts (e.g., for make check), the binaries will be named foo.exe instead of foo. Or possibly if we're running on a DOSISH system. */ ext = find_suffix (program_invocation_short_name); if (ext && FILESTRCASEEQ (ext, "exe")) { kpse_program_name = remove_suffix (program_invocation_short_name); } else { kpse_program_name = xstrdup (program_invocation_short_name); } } xputenv("progname", kpse_program_name); }
static boolean doIoSuppOpenSrc( // OPEN A SOURCE FILE (PRIMARY,HEADER) struct path_descr *fd, // - descriptor for file name enum file_type typ ) // - type of search path to use { char **paths; // - optional paths to prepend char **exts; // - optional extensions to append boolean retn; // - return: TRUE ==> opened char *path; // - next path char bufpth[ _MAX_PATH ]; // - buffer for next path SRCFILE curr; // - current included file SRCFILE stdin_srcfile; // - srcfile for stdin struct path_descr idescr; // - descriptor for included file LINE_NO dummy; // - dummy line number holder char prevpth[ _MAX_PATH ]; // - buffer for previous path switch( typ ) { case FT_SRC: if( fd->fnm[0] == '\0' && fd->ext[0] == '.' && fd->ext[1] == '\0' ) { if( ErrCount != 0 ) { // command line errors may result in "." as the input name // so the user thinks that the compiler is hung! return( FALSE ); } WholeFName = FNameAdd( "stdin" ); stdin_srcfile = SrcFileOpen( stdin, WholeFName ); SrcFileNotAFile( stdin_srcfile ); goto file_was_found; } paths = pathSrc; exts = extsSrc; break; case FT_HEADER: case FT_LIBRARY: if( !CompFlags.ignore_current_dir ) { paths = pathHdr; } else { paths = NULL; } exts = extsHdr; break; case FT_CMD: paths = pathCmd; exts = extsCmd; break; } switch( typ ) { case FT_LIBRARY: if( fd->drv[0] != '\0' || IS_DIR_SEP( fd->dir[0] ) ) { retn = openSrcPath( "", exts, fd, typ ); if( retn ) goto file_was_found; } break; case FT_HEADER: // even if ignoreing current dir, have to look for absolute paths if( !CompFlags.ignore_current_dir || fd->drv[0] != '\0' ) { // look in current directory retn = openSrcPath( "", exts, fd, typ ); if( retn ) goto file_was_found; } /* check directories of currently included files */ if( !IS_PATH_SEP( fd->dir[0] ) ) { prevpth[0] = '\xff'; /* to make it not compare with anything else */ prevpth[1] = '\0'; curr = SrcFileCurrent(); for( ;; ) { if( curr == NULL ) break; splitFileName( SrcFileName( curr ), &idescr ); _makepath( bufpth, idescr.drv, idescr.dir, NULL, NULL ); /*optimization: don't try and open if in previously checked dir*/ if( strcmp( bufpth, prevpth ) != 0 ) { retn = openSrcPath( bufpth, exts, fd, FT_HEADER ); if( retn ) goto file_was_found; } curr = SrcFileIncluded( curr, &dummy ); strcpy( prevpth, bufpth ); } } break; case FT_SRC: case FT_CMD: retn = openSrcPath( "", exts, fd, typ ); if( retn ) goto file_was_found; break; } switch( typ ) { case FT_HEADER: case FT_LIBRARY: HFileListStart(); for( ; ; ) { HFileListNext( bufpth ); if( *bufpth == '\0' ) break; retn = openSrcPath( bufpth, exts, fd, typ ); if( retn ) goto file_was_found; } break; } switch( typ ) { case FT_HEADER: case FT_CMD: case FT_SRC: if( IS_PATH_SEP( fd->dir[0] ) ) { // absolute path break; } if( paths != NULL ) { for( ; ; ) { path = *paths++; if( path == NULL ) break; retn = openSrcPath( path, exts, fd, typ ); if( retn ) goto file_was_found; } } break; } return FALSE; file_was_found: switch( typ ) { case FT_CMD: SrcFileCommand(); break; case FT_LIBRARY: SrcFileLibrary(); break; } return TRUE; }
boolean open_input (FILE **f_ptr, int filefmt, const_string fopen_mode) { string fname = NULL; #ifdef FUNNY_CORE_DUMP /* This only applies if a preloaded TeX/Metafont is being made; it allows automatic creation of the core dump (typing ^\ loses since that requires manual intervention). */ if ((filefmt == kpse_tex_format || filefmt == kpse_mf_format || filefmt == kpse_mp_format) && STREQ (nameoffile + 1, "HackyInputFileNameForCoreDump.tex")) funny_core_dump (); #endif /* We havent found anything yet. */ *f_ptr = NULL; if (fullnameoffile) free(fullnameoffile); fullnameoffile = NULL; /* Look in -output-directory first, if the filename is not absolute. This is because .aux and other such files will get written to the output directory, and we have to be able to read them from there. We only look for the name as-is. */ if (output_directory && !kpse_absolute_p (nameoffile+1, false)) { fname = concat3 (output_directory, DIR_SEP_STRING, nameoffile + 1); *f_ptr = fopen (fname, fopen_mode); if (*f_ptr) { free (nameoffile); namelength = strlen (fname); nameoffile = xmalloc (namelength + 2); strcpy (nameoffile + 1, fname); fullnameoffile = fname; } else { free (fname); } } /* No file means do the normal search. */ if (*f_ptr == NULL) { /* A negative FILEFMT means don't use a path. */ if (filefmt < 0) { /* no_file_path, for BibTeX .aux files and MetaPost things. */ *f_ptr = fopen(nameoffile + 1, fopen_mode); /* FIXME... fullnameoffile = xstrdup(nameoffile + 1); */ } else { /* The only exception to `must_exist' being true is \openin, for which we set `tex_input_type' to 0 in the change file. */ /* According to the pdfTeX people, pounding the disk for .vf files is overkill as well. A more general solution would be nice. */ boolean must_exist = (filefmt != kpse_tex_format || texinputtype) && (filefmt != kpse_vf_format); fname = kpse_find_file (nameoffile + 1, (kpse_file_format_type)filefmt, must_exist); if (fname) { fullnameoffile = xstrdup(fname); /* If we found the file in the current directory, don't leave the `./' at the beginning of `nameoffile', since it looks dumb when `tex foo' says `(./foo.tex ... )'. On the other hand, if the user said `tex ./foo', and that's what we opened, then keep it -- the user specified it, so we shouldn't remove it. */ if (fname[0] == '.' && IS_DIR_SEP (fname[1]) && (nameoffile[1] != '.' || !IS_DIR_SEP (nameoffile[2]))) { unsigned i = 0; while (fname[i + 2] != 0) { fname[i] = fname[i + 2]; i++; } fname[i] = 0; } /* kpse_find_file always returns a new string. */ free (nameoffile); namelength = strlen (fname); nameoffile = xmalloc (namelength + 2); strcpy (nameoffile + 1, fname); free (fname); /* This fopen is not allowed to fail. */ #if defined(PTEX) && !defined(WIN32) if (filefmt == kpse_tex_format || filefmt == kpse_bib_format) { *f_ptr = nkf_open (nameoffile + 1, fopen_mode); } else #endif *f_ptr = xfopen (nameoffile + 1, fopen_mode); } } } if (*f_ptr) { recorder_record_input (nameoffile + 1); /* If we just opened a TFM file, we have to read the first byte, to pretend we're Pascal. See tex.ch and mp.ch. Ditto for the ocp/ofm Omega file formats. */ if (filefmt == kpse_tfm_format) { tfmtemp = getc (*f_ptr); /* We intentionally do not check for EOF here, i.e., an empty TFM file. TeX will see the 255 byte and complain about a bad TFM file, which is what we want. */ } else if (filefmt == kpse_ocp_format) { ocptemp = getc (*f_ptr); } else if (filefmt == kpse_ofm_format) { tfmtemp = getc (*f_ptr); } } return *f_ptr != NULL; }
_WCRTLINK void __F_NAME(_splitpath,_wsplitpath)( const CHAR_TYPE *path, CHAR_TYPE *drive, CHAR_TYPE *dir, CHAR_TYPE *fname, CHAR_TYPE *ext ) { const CHAR_TYPE *dotp; const CHAR_TYPE *fnamep; const CHAR_TYPE *startp; UINT_WC_TYPE ch; #ifdef __NETWARE__ const CHAR_TYPE *ptr; #endif /* take apart specification like -> //0/hd/user/fred/filename.ext for QNX */ /* take apart specification like -> c:\fred\filename.ext for DOS, OS/2 */ #if defined(__UNIX__) /* process node/drive specification */ startp = path; if( path[0] == DIR_SEP && path[1] == DIR_SEP ) { path += 2; for( ;; ) { if( *path == NULLCHAR ) break; if( *path == DIR_SEP ) break; if( *path == STRING( '.' ) ) break; ++path; } } copypart( drive, startp, path - startp, _MAX_NODE ); #elif defined(__NETWARE__) #ifdef __WIDECHAR__ ptr = wcschr( path, DRV_SEP ); #else ptr = _mbschr( (unsigned char *)path, DRV_SEP ); #endif if( ptr != NULL ) { if( drive != NULL ) { copypart( drive, path, ptr - path + 1, _MAX_SERVER + _MAX_VOLUME + 1 ); } #if defined( __WIDECHAR__ ) path = ptr + 1; #else path = _mbsinc( ptr ); #endif } else if( drive != NULL ) { *drive = NULLCHAR; } #else /* processs drive specification */ if( path[0] != NULLCHAR && path[1] == DRV_SEP ) { if( drive != NULL ) { drive[0] = path[0]; drive[1] = DRV_SEP; drive[2] = NULLCHAR; } path += 2; } else if( drive != NULL ) { drive[0] = NULLCHAR; } #endif /* process /user/fred/filename.ext for QNX */ /* process /fred/filename.ext for DOS, OS/2 */ dotp = NULL; fnamep = path; startp = path; for( ;; ) { /* 07-jul-91 DJG -- save *path in ch for speed */ if( *path == NULLCHAR ) break; #if defined( __WIDECHAR__ ) || defined( __UNIX__ ) || defined( __RDOS__ ) || defined( __RDOSDEV__ ) ch = *path; #else ch = _mbsnextc( (unsigned char *)path ); #endif if( ch == EXT_SEP ) { dotp = path; ++path; continue; } #if defined( __WIDECHAR__ ) || defined( __UNIX__ ) || defined( __RDOS__ ) || defined( __RDOSDEV__ ) ++path; #else path = (char *)_mbsinc( (unsigned char *)path ); #endif if( IS_DIR_SEP( ch ) ) { fnamep = path; dotp = NULL; } } copypart( dir, startp, fnamep - startp, _MAX_DIR - 1 ); if( dotp == NULL ) dotp = path; copypart( fname, fnamep, dotp - fnamep, _MAX_FNAME - 1 ); copypart( ext, dotp, path - dotp, _MAX_EXT - 1); }