AcePerl

 view release on metacpan or  search on metacpan

acelib/filsubs.c  view on Meta::CPAN

{
  char *home ;

  if (!dirPath)
    dirPath = stackCreate (128) ;

  /* if the user directory is specified */
  if (*s == '~' &&
		(home = getenv (HOME_DIR_ENVP))) /* substitute */
    {
#if defined(WIN32) /* in WIN32, need to prefix homepath with home drive*/
      char *drive;
      drive = getenv ("HOMEDRIVE") ;
	  pushText(dirPath, drive) ;
	  catText(dirPath, home) ;
#else
      pushText (dirPath, home) ;
#endif
      catText (dirPath, ++s) ;
    }
  else
    pushText (dirPath, s) ;

  catText (dirPath, SUBDIR_DELIMITER_STR) ;

  return;
} /* filAddDir */

/*********************************************/

UTIL_FUNC_DEF void filAddPath (char *cp)
{
  char *cq = cp ;

  while (TRUE)
    { 
      while (*cq && *cq != PATH_DELIMITER)
	++cq ;
      if (*cq == PATH_DELIMITER)
	{
	  *cq = 0 ;
	  filAddDir (cp) ;
	  cp = ++cq ;
	}
      else
	{ 
	  filAddDir (cp) ;
	  break ;
	}
    }

  return;
} /* filAddPath */


/*****************************************************************************/
/* This function returns the filename part of a given path,                  */
/*                                                                           */
/*   Given   "/some/load/of/directories/filename"  returns  "filename"       */
/*                                                                           */
/* The function returns NULL for the following errors:                       */
/*                                                                           */
/* 1) supplying a NULL ptr as the path                                       */
/* 2) supplying "" as the path                                               */
/* 3) supplying a path that ends in "/"                                      */
/*                                                                           */
/* NOTE, this function is _NOT_ the same as the UNIX basename command or the */
/* XPG4_UNIX basename() function which do different things.                  */
/*                                                                           */
/* The function makes a copy of the supplied path on which to work, this     */
/* copy is thrown away each time the function is called.                     */
/*                                                                           */
/*****************************************************************************/

UTIL_FUNC_DEF char *filGetFilename(char *path)
{
  static char *path_copy = NULL ;
  const char *path_delim = SUBDIR_DELIMITER_STR ;
  char *result = NULL, *tmp ;
    
  if (path != NULL)
    {
      if (strcmp((path + strlen(path) - 1), path_delim) != 0) /* Last char = "/" ?? */
	{
	  if (path_copy != NULL) messfree(path_copy) ;
	  
	  path_copy = strnew(path, 0) ;
	  
	  tmp = path ;
	  while (tmp != NULL)
	    {
	      result = tmp ;
	      
	      tmp = strstr(tmp, path_delim) ;
	      if (tmp != NULL) tmp++ ;
	    }
	}
    }
  
  return(result) ;
} /* filGetFilename */


/*****************************************************************************/
/* This function returns the file-extension part of a given path/filename,   */
/*                                                                           */
/*   Given   "/some/load/of/directories/filename.ext"  returns  "ext"        */
/*                                                                           */
/* The function returns NULL for the following errors:                       */
/*                                                                           */
/* 1) supplying a NULL ptr as the path                                       */
/* 2) supplying a path with no filename                                      */
/*                                                                           */
/* The function returns "" for a filename that has no extension              */
/*                                                                           */
/* The function makes a copy of the supplied path on which to work, this     */
/* copy is thrown away each time the function is called.                     */
/*                                                                           */
/*****************************************************************************/
UTIL_FUNC_DEF char *filGetExtension(char *path)
{
  static char *path_copy = NULL ;
  char *extension = NULL, *cp ;
    
  if (path == NULL)
    return NULL;

  if (strlen(path) == 0)
    return NULL;

  if (path_copy != NULL) messfree(path_copy) ;
  path_copy = messalloc ((strlen(path)+1) * sizeof(char));
  strcpy (path_copy, path);

  cp = path_copy + (strlen(path_copy) - 1);
  while (cp > path_copy &&
	 *cp != SUBDIR_DELIMITER &&
	 *cp != '.')
    --cp;

  extension = cp+1;
    
  return(extension) ;
} /* filGetExtension */


/**********************************************************************/
/* This function takes a directory name and does the following:
   1. Returns the name if it is "complete" 
      (an absolute path on a given platform)
   2. On WIN32 platforms, for onto rooted paths	lacking a 
      drive specification, returns the directory name prefixed with 
      the default drive letter 
   3. Otherwise, assumes that the directory name resides within the 
      current working directory and thus, returns it prefixes the
      directory name with the working directory path */
/**********************************************************************/
UTIL_FUNC_DEF char *filGetFullPath(char *dir)
{
  static char *path_copy = NULL;
  char *pwd ;
  char dirbuf[MAXPATHLEN] ;

  /* Return dir if absolute path already */
  if (ABSOLUTE_PATH(dir))
    { 
      if (path_copy) 
	messfree (path_copy);
      path_copy = (char*) messalloc (strlen(dir) + 1) ;
      strcpy (path_copy, dir) ;
      return path_copy ;
    }

#if defined(WIN32)
  /* else if dir is a Win32 rooted path, then add current drive to rooted paths */
  else if ( *dir == SUBDIR_DELIMITER )
    { 
      char drive[3] = { GET_CURRENT_DRIVE, DRIVE_DELIMITER, '\0' } ;
      
      if (path_copy)
	messfree (path_copy);

      path_copy = (char*) messalloc (strlen(dir) + strlen(drive) + 1) ;
      strcpy (path_copy, drive) ;
      strcat (path_copy, dir) ;

      return path_copy ;
    }
#endif

  /* else if I can, then prefix "dir" with working directory path... */
  else if ((pwd = getwd (dirbuf)))
    { 
      if (path_copy)
	messfree (path_copy);

      path_copy = (char*) messalloc (strlen(pwd) + strlen(dir) + 2) ;

      strcpy (path_copy, pwd) ;
      strcat (path_copy, SUBDIR_DELIMITER_STR) ;
      strcat (path_copy, dir) ;

      return path_copy ;
    }
  else
    return 0 ;  /* signals error that the path was not found */
} /* filGetFullPath */

/*******************************/

static BOOL filCheck (char *name, char *spec)
	/* allow 'd' as second value of spec for a directory */
{
  char *cp ;
  BOOL result ;
  struct stat status ;

  if (!spec) /* so filName returns full file name (for error messages) */
    return TRUE ;
				/* directory check */
  if (spec[1] == 'd'  &&
      (stat (name, &status) || !(status.st_mode & S_IFDIR)))
    return 0 ;

  switch (*spec)
    {
    case 'r':
      return !(access (name, R_OK)) ;
    case 'w':
    case 'a':
      if (!access (name, W_OK))	/* requires file exists */
	return TRUE ;
				/* test directory writable */
      cp = name + strlen (name) ;
      while (cp > name)
	if (*--cp == SUBDIR_DELIMITER) break ;
      if (cp == name)
	return !(access (".", W_OK)) ;
      else
	{ *cp = 0 ;
	  result = !(access (name, W_OK)) ;
	  *cp = SUBDIR_DELIMITER ;
	  return result ;
	}
    case 'x':
      return !(access (name, X_OK)) ;
    default:
      messcrash ("Unknown spec %s passed to filName", spec) ;
    }
  return FALSE ;
}

/************************************************/

static char *filDoName (char *name, char *ending, char *spec, BOOL strict)
{
  static Stack part = 0, full = 0 ;
  char *dir, *result ;
#if defined(WIN32)
  char *cp, buf2[2] ;
  static char driveStr[3] = { 'C', DRIVE_DELIMITER, '\0' },
			  *pDriveStr = driveStr ; 
#endif

  if (!name)
    messcrash ("filName received a null name") ;

  if (!part)
    { part = stackCreate (128) ;
      full = stackCreate (MAXPATHLEN) ;
    }
    
  stackClear (part) ;

#if defined(WIN32)
  /* convert '/' => '\\' in path string */
  cp = name ; buf2[1] = 0 ;
  while (*cp)

acelib/filsubs.c  view on Meta::CPAN

      driveStr[0] = GET_CURRENT_DRIVE ;
      catText (full, pDriveStr ) ;
      catText (full, stackText (part, 0)) ;
      result = stackText (full, 0) ;
      if (filCheck (result, spec))
	return result ;
      else
	return 0 ;
    }
#endif
  
  if (!dirPath)			/* add cwd as default to search */
    filAddDir (getwd (stackText (full, 0))) ;
  stackCursor (dirPath, 0) ;
  while ((dir = stackNextText (dirPath)))
    { 
      stackClear (full) ;
      catText (full, dir) ;
      catText (full, stackText (part, 0)) ;
      result = stackText (full, 0) ;
      if (filCheck (result, spec))
	return result ;
      if (strict)
	break ;
    }
  return 0 ;
} /* filDoName */

/************************************************************/

UTIL_FUNC_DEF char *filName (char *name, char *ending, char *spec)
{ return filDoName(name, ending, spec, FALSE) ; }

/************************************************************/

UTIL_FUNC_DEF char *filStrictName (char *name, char *ending, char *spec)
{ return filDoName(name, ending, spec, TRUE) ; }

/************************************************************/

UTIL_FUNC_DEF BOOL filremove (char *name, char *ending) 
				/* TRUE if file is deleted. -HJC*/
{
  char *s = filName (name, ending, "r") ;
  if (s)
    return unlink(s) ? FALSE : TRUE ;
  else
    return FALSE ;
} /* filremove */

/************************************************************/

UTIL_FUNC_DEF FILE *filopen (char *name, char *ending, char *spec)
{
  char *s = filName (name, ending, spec) ;
  FILE *result = 0 ;
   
  if (!s)
    {
      if (spec[0] == 'r')
	messerror ("Failed to open for reading: %s (%s)",
		   filName (name, ending,0),
		   messSysErrorText()) ;
      else if (spec[0] == 'w')
	messerror ("Failed to open for writing: %s (%s)",
		   filName (name, ending,0),
		   messSysErrorText()) ;
      else if (spec[0] == 'a')
	messerror ("Failed to open for appending: %s (%s)",
		   filName (name, ending,0),
		   messSysErrorText()) ;
      else
	messcrash ("filopen() received invalid filespec %s",
		   spec ? spec : "(null)");
    }
  else if (!(result = fopen (s, spec)))
    {
      messerror ("Failed to open %s (%s)",
		 s, messSysErrorText()) ;
    }
  return result ;
} /* filopen */

/********************* temporary file stuff *****************/

static Associator tmpFiles = 0 ;

UTIL_FUNC_DEF FILE *filtmpopen (char **nameptr, char *spec)
{
  if (!nameptr)
    messcrash ("filtmpopen requires a non-null nameptr") ;

  if (!strcmp (spec, "r"))
    return filopen (*nameptr, 0, spec) ;

#if defined(SUN) || defined(SOLARIS)
  if (!(*nameptr = tempnam ("/var/tmp", "ACEDB")))
#else
  if (!(*nameptr = tempnam ("/tmp", "ACEDB")))
#endif
    { 
      messerror ("failed to create temporary file (%s)",
		 messSysErrorText()) ;
      return 0 ;
    }
  if (!tmpFiles)
    tmpFiles = assCreate () ;
  assInsert (tmpFiles, *nameptr, *nameptr) ;

  return filopen (*nameptr, 0, spec) ;
} /* filtmpopen */

/************************************************************/

UTIL_FUNC_DEF BOOL filtmpremove (char *name)	/* delete and free()  */
{ BOOL result = filremove (name, 0) ;

  free (name) ;	/* NB free since allocated by tempnam */
  assRemove (tmpFiles, name) ;
  return result ;
}

/************************************************************/

UTIL_FUNC_DEF void filtmpcleanup (void)
{ char *name = 0 ;
 
  if (tmpFiles)
    while (assNext (tmpFiles, &name, 0))
      { filremove (name, 0) ;
	free (name) ;
      }
}

/************* filqueryopen() ****************/

static QueryOpenRoutine queryOpenFunc = 0 ;

UTIL_FUNC_DEF QueryOpenRoutine filQueryOpenRegister (QueryOpenRoutine new)
{ QueryOpenRoutine old = queryOpenFunc ; queryOpenFunc = new ; return old ; }

UTIL_FUNC_DEF FILE *filqueryopen (char *dname, char *fname, char *end, char *spec, char *title)
{
  Stack s ;
  FILE*	fil = 0 ;
  int i ;
				/* use registered routine if available */
  if (queryOpenFunc)
    return (*queryOpenFunc)(dname, fname, end, spec, title) ;

  /* otherwise do here and use messprompt() */
  s = stackCreate(50);

  if (dname && *dname)
    { pushText(s, dname) ; catText(s,"/") ; }
  if (fname)
    catText(s,fname) ; 
  if (end && *end)
    { catText(s,".") ; catText(s,end) ; }

 lao:
  if (!messPrompt("File name please", stackText(s,0), "w")) 
    { stackDestroy(s) ;
      return 0 ;
    }
  i = stackMark(s) ;
  pushText(s, freepath()) ;	/* freepath needed by WIN32 */
  if (spec[0] == 'w' && 
      (fil = fopen (stackText(s,i), "r")))
    { if ( fil != stdin && fil != stdout && fil != stderr)
	fclose (fil) ; 
      fil = 0 ;
      if (messQuery (messprintf ("Overwrite %s?",
				 stackText(s,i))))
	{ 
	  if ((fil = fopen (stackText(s,i), spec)))
	    goto bravo ;
	  else
	    messout ("Sorry, can't open file %s for writing",
		     stackText (s,i)) ;
	}
      goto lao ;
    }
  else if (!(fil = fopen (stackText(s,i), spec))) 
    messout ("Sorry, can't open file %s",
	     stackText(s,i)) ;
bravo:
  stackDestroy(s) ;
  return fil ;
} /* filqueryopen */

/*********************************************/

static Associator mailFile = 0, mailAddress = 0 ;

UTIL_FUNC_DEF void filclose (FILE *fil)
{
  char *address ;
  char *filename ;

  if (!fil || fil == stdin || fil == stdout || fil == stderr)
    return ;
  fclose (fil) ;
  if (mailFile && assFind (mailFile, fil, &filename))
    { if (assFind (mailAddress, fil, &address))
	callScript ("mail", messprintf ("%s %s", address, filename)) ;
      else
	messerror ("Have lost the address for mailfile %s", filename) ;
      assRemove (mailFile, fil) ;
      assRemove (mailAddress, fil) ;
      unlink (filename) ;
      free (filename) ;
    }
} /* filclose */

/***********************************/

UTIL_FUNC_DEF FILE *filmail (char *address)	/* requires filclose() */
{
  char *filename ;
  FILE *fil ;

  if (!mailFile)
    { mailFile = assCreate () ;
      mailAddress = assCreate () ;
    }
  if (!(fil = filtmpopen (&filename, "w")))
    { messout ("failed to open temporary mail file %s", filename) ;
      return 0 ;
    }
  assInsert (mailFile, fil, filename) ;
  assInsert (mailAddress, fil, address) ;
  return fil ;
} /* filmail */

/******************* directory stuff *************************/

static int dirOrder(void *a, void *b)
{
  char *cp1 = *(char **)a, *cp2 = *(char**)b;
  return strcmp(cp1, cp2) ;
} /* dirOrder */

/* returns an Array of strings representing the filename in the
   given directory according to the spec. "r" will list all files,
   and "rd" will list all directories.
   The behaviour of the "w" spec is undefined.
   The array has to be destroyed using filDirectoryDestroy,
   because the memory of the strings needs to be reclaimed as well. */

UTIL_FUNC_DEF Array filDirectoryCreate (char *dirName,
					char *ending, 
					char *spec)
{
  Array a ;
#if !defined(WIN32) && !defined(DARWIN)
  DIR	*dirp ;
  char	*dName, *dName_copy, entryPathName[MAXPATHLEN], *leaf ;
  int	dLen, endLen ;
  MYDIRENT *dent ;

  if (!dirName || !(dirp = opendir (dirName)))
    return 0 ;

  if (ending)
    endLen = strlen (ending) ;
  else
    endLen = 0 ;



( run in 2.648 seconds using v1.01-cache-2.11-cpan-39bf76dae61 )