Exemplo n.º 1
0
/*
 * 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);
}
Exemplo n.º 2
0
/*
 * 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;
}
Exemplo n.º 3
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';
}
Exemplo n.º 4
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;
}
Exemplo n.º 5
0
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 */
}
Exemplo n.º 6
0
_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 );
}
Exemplo n.º 7
0
/* 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;
}
Exemplo n.º 8
0
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 );
}
Exemplo n.º 9
0
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 );
}
Exemplo n.º 10
0
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 );
}
Exemplo n.º 11
0
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 );
}
Exemplo n.º 12
0
_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;
}
Exemplo n.º 13
0
/* 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
}
Exemplo n.º 14
0
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;
}
Exemplo n.º 15
0
/***********************************************************************
 * 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;
}
Exemplo n.º 16
0
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 */
}
Exemplo n.º 17
0
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;
}
Exemplo n.º 18
0
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;
}
Exemplo n.º 19
0
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;
}
Exemplo n.º 20
0
/*
 * 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 */
		}
	}
Exemplo n.º 21
0
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 */
}
Exemplo n.º 22
0
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);
}
Exemplo n.º 23
0
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;
}
Exemplo n.º 24
0
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;
}
Exemplo n.º 25
0
_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);
}