Open64 (mfef90, whirl2f, and IR tools)  TAG: version-openad; SVN changeset: 916
file_util.c
Go to the documentation of this file.
00001 /*
00002 
00003   Copyright (C) 2000, 2001 Silicon Graphics, Inc.  All Rights Reserved.
00004 
00005   This program is free software; you can redistribute it and/or modify it
00006   under the terms of version 2 of the GNU General Public License as
00007   published by the Free Software Foundation.
00008 
00009   This program is distributed in the hope that it would be useful, but
00010   WITHOUT ANY WARRANTY; without even the implied warranty of
00011   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
00012 
00013   Further, this software is distributed without any warranty that it is
00014   free of the rightful claim of any third person regarding infringement 
00015   or the like.  Any license provided herein, whether implied or 
00016   otherwise, applies only to this software file.  Patent licenses, if 
00017   any, provided herein do not apply to combinations of this program with 
00018   other software, or any other product whatsoever.  
00019 
00020   You should have received a copy of the GNU General Public License along
00021   with this program; if not, write the Free Software Foundation, Inc., 59
00022   Temple Place - Suite 330, Boston MA 02111-1307, USA.
00023 
00024   Contact information:  Silicon Graphics, Inc., 1600 Amphitheatre Pky,
00025   Mountain View, CA 94043, or:
00026 
00027   http://www.sgi.com
00028 
00029   For further information regarding this notice, see:
00030 
00031   http://oss.sgi.com/projects/GenInfo/NoticeExplan
00032 
00033 */
00034 
00035 
00036 
00037 static char *source_file = __FILE__;
00038 
00039 #include <sys/types.h>
00040 #include <sys/stat.h>
00041 #include <unistd.h>
00042 #include <sys/param.h>
00043 #include <stdlib.h>
00044 #include <stdio.h>
00045 #include <cmplrs/rcodes.h>
00046 
00047 #include "defs.h"
00048 #include "file_util.h"
00049 
00050 /* ====================================================================
00051  *
00052  * Is_File
00053  *
00054  * Determine whether a pathname represents an existing regular file.
00055  *
00056  * ====================================================================
00057  */
00058 
00059 BOOL
00060 Is_File ( const char *fname )
00061 {
00062     struct stat desc;               /* File status descriptor */
00063 
00064     if (fname == NULL)
00065         return FALSE;
00066   
00067     if ( stat ( fname, &desc ) != 0 )
00068         return FALSE;               /* existing? */
00069     return ( (desc.st_mode & S_IFREG) != 0 ); /* regular file? */
00070 }
00071 
00072 
00073 /* ====================================================================
00074  *
00075  * Same_File
00076  *
00077  * Determine whether two streams are associated with the same file.
00078  * Returns FALSE (not the same) if there are any problems obtaining
00079  * status.
00080  *
00081  * ====================================================================
00082  */
00083 
00084 BOOL
00085 Same_File ( file1, file2 )
00086   FILE *file1, *file2;
00087 {
00088   struct stat d1, d2;   /* Stream status descriptors */
00089 
00090   if ( file1 == NULL || file2 == NULL ) return FALSE;
00091   if ( fstat ( fileno(file1), &d1 ) == -1 ) return FALSE;
00092   if ( fstat ( fileno(file2), &d2 ) == -1 ) return FALSE;
00093   return ( d1.st_ino == d2.st_ino ) && ( d1.st_dev == d2.st_dev );
00094 }
00095 
00096 #ifndef MONGOOSE_BE
00097 /* ====================================================================
00098  *
00099  * Find_File
00100  *
00101  * Search for a file with a specific extension.  First look for the
00102  * name given; if not found, and the name does not already have the
00103  * given extension, look for the name with the extension appended.
00104  * The name string passed must have enough space to append the
00105  * extension, and if that is the form found, it will be appended on
00106  * return.
00107  *
00108  * ====================================================================
00109  */
00110 
00111 BOOL
00112 Find_File ( name, ext )
00113   char *name;   /* The initial filename to search for */
00114   char *ext;    /* The default extension to try */
00115 {
00116   INT16 len;
00117 
00118   /* Check for the initial filename: */
00119   if ( Is_File(name) ) return TRUE;
00120 
00121   /* Try appending the default extension: */
00122   if ( ! Has_Extension ( name, ext ) ) {
00123     len = strlen(name);
00124     strcat (name, ext);
00125     if ( Is_File(name) ) return TRUE;
00126     name[len] = 0;      /* Restore the original file name */
00127   }
00128 
00129   /* Nothing worked */
00130   return FALSE;
00131 }
00132 
00133 /* ====================================================================
00134  *
00135  * Has_Extension
00136  *
00137  * Determine whether a filename has a given extension.
00138  *
00139  * ====================================================================
00140  */
00141 
00142 BOOL
00143 Has_Extension ( name, ext )
00144   char *name;   /* The filename to check */
00145   char *ext;    /* The extension to look for */
00146 {
00147   INT16 nlen = strlen(name);
00148   INT16 elen = strlen(ext);
00149 
00150   /* If ext is longer than name, no chance: */
00151   if ( elen > nlen ) return FALSE;
00152 
00153   /* Otherwise compare the tail of name to ext: */
00154   return ( strcmp ( &name[nlen-elen], ext ) == 0 );
00155 }
00156 #endif /* MONGOOSE_BE */
00157 
00158 
00159 /* ====================================================================
00160  *
00161  * New_Extension
00162  *
00163  * Replace the given file name's extension with another extension and
00164  * return a new filename string.  The given extension should include
00165  * the period if desired (a period in the original name will be
00166  * eliminated).
00167  *
00168  * ====================================================================
00169  */
00170 
00171 char *
00172 New_Extension ( const char *name, const char *ext )
00173 {
00174   char *new;
00175   INT16 len, i;
00176 
00177   /* Allocate a new name string: */
00178   len = strlen(name);
00179   new = (char *) malloc ( len + strlen(ext) + 1 );
00180   strcpy ( new, name );
00181   for ( i=len-1; i>=0; i-- ) {
00182     if ( new[i] == '/' ) break; /* Don't touch directory prefixes */
00183     if ( new[i] == '.' ) {
00184       new[i] = 0;
00185       break;
00186     }
00187   }
00188   strcat ( new, ext );
00189   return new;
00190 }
00191 
00192 /* ====================================================================
00193  *
00194  * Remove_Extension
00195  *
00196  * Remove the extension from a given file name. The period in the
00197  * original file name is also removed. Assumes that the directory
00198  * prefixes have already been removed.
00199  *
00200  * ====================================================================
00201  */
00202 
00203 char *
00204 Remove_Extension ( name )
00205   char *name; /* The file name with extension */
00206 {
00207   char *new;
00208   INT16 len, i;
00209   /* Allocate a new name string: */
00210   len = strlen(name);
00211   new = (char *) malloc ( len );
00212   strcpy ( new, name );
00213   for ( i=len-1; i>=0; i-- ) {
00214     if ( new[i] == '.' ) {
00215       new[i] = 0;
00216       break;
00217     }
00218   }
00219   return new;
00220 }
00221 
00222 
00223 #ifndef MONGOOSE_BE
00224 /* ====================================================================
00225  *
00226  * Make_Temp_File
00227  *
00228  * Make a temporary file name from a temporary directory name, a file
00229  * name prefix, and the process ID.
00230  *
00231  * ====================================================================
00232  */
00233 
00234 char *
00235 Make_Temp_File ( tmp, prefix )
00236   char *tmp;    /* Temporary directory pathname to use */
00237   char *prefix; /* Prefix for file name */
00238 {
00239   INT16 len = strlen(tmp);
00240   char *name;   /* Result temporary file pathname */
00241 
00242   name = (char *) malloc (len + 20);
00243   if ( len > 0 ) {
00244     strcpy ( name, tmp );
00245     name[len++] = '/';
00246   }
00247   strcpy ( &name[len], prefix );
00248   len += strlen(prefix);
00249   sprintf ( &name[len], "%d", getpid() );
00250   return name;
00251 }
00252 
00253 /* current working directory */
00254 static char *cwd = NULL;
00255 static INT cwd_size;
00256 
00257 char *
00258 Get_Current_Working_Directory (void)
00259 {
00260   char *cwd;
00261   cwd = getcwd((char *) NULL, MAXPATHLEN);
00262   if (cwd == NULL) {
00263     cwd = getenv("PWD");
00264         if (cwd == NULL) {
00265                 /* can't get path */
00266                 cwd = ".";
00267         }
00268   }
00269   return cwd;
00270 }
00271 
00272 /* ====================================================================
00273  *
00274  * Full_Path_Name
00275  *
00276  * Make a full path name from a base file name.
00277  *
00278  * ====================================================================
00279  */
00280 
00281 char *
00282 Full_Path_Name ( base, path, pathlen )
00283   char *base;   /* Base file name (may be full pathname) */
00284   char *path;   /* String to receive pathname */
00285   INT pathlen;  /* Length of path -- exceeding is a fatal error */
00286 {
00287   INT baselen;
00288 
00289   /* If the base name is NULL, just give up: */
00290   if ( base == NULL ) return NULL;
00291   baselen = strlen (base);
00292   if ( baselen > pathlen ) exit(RC_SYSTEM_ERROR);
00293 
00294   /* If the base name is a full path, just copy it and return: */
00295   if (base[0] == '/') {
00296     strcpy (path, base);
00297     return NULL;
00298   }
00299 
00300   /* Otherwise prepend the current working directory name: */
00301   if ( cwd == NULL ) {
00302         cwd = Get_Current_Working_Directory();
00303         cwd_size = strlen (cwd);
00304   }
00305   if ( baselen + cwd_size > pathlen ) exit(RC_SYSTEM_ERROR);
00306   strcpy (path, cwd);
00307   strcat (path, "/");
00308   strcat (path, base);
00309   return path;
00310 }
00311 #endif /* MONGOOSE_BE */
00312 
00313 /* ====================================================================
00314  *
00315  * Last_Pathname_Component
00316  *
00317  * Return the last component of the pathname specified in 'pname'.
00318  * I.e., if the input is "/da/db/dc/f.x", return a pointer to "f.x".
00319  * If there are no slashes in the input, just return the input.
00320  *
00321  * Note that we return a pointer to a portion of the input string.
00322  * Therefore, if our caller wants to modify the returned value, the
00323  * caller must first make a copy.
00324  *
00325  * ====================================================================
00326  */
00327 
00328 char *
00329 Last_Pathname_Component ( char *pname )
00330 {
00331   char *cp = pname + strlen(pname);
00332 
00333   while (cp != pname) {
00334     if (*cp == '/') return cp+1;
00335     --cp;
00336   }
00337   if (*cp == '/') return cp+1;
00338   return cp;
00339 
00340 } /*end: Last_Pathname_Component */
00341 
00342 
00343 #ifndef MONGOOSE_BE
00344 /* Eliminates "//", "/.", and "/.." from the path, to the extent that it
00345  * is possible.
00346  * "//"      -> "/"
00347  * "/./"     -> "/"
00348  * "a/b/../" -> "a/"
00349  */
00350 static char *
00351 normalize_path(char * path)
00352 {
00353   char * inp = path, *outp = path, *tmp;
00354 
00355   while (inp != NULL && *inp != '\0') {
00356     if (inp[0] == '/') {
00357       if (inp[1] == '/')
00358         inp+= 1;
00359       else if (inp[1] == '.' && inp[2] == '/')
00360         inp += 2;
00361       else if (inp[1] == '.' && inp[2] == '.' && inp[3] == '/') {
00362         /* Skip up one level up output path */
00363         for (tmp = outp-1;
00364              tmp >= path && *tmp != '/';
00365              tmp -= 1);
00366         /* Check that we skipped one level up, but not past ".." */
00367         if (tmp >= path && tmp[0] == '/' && 
00368           (tmp[1] != '.' || tmp[2] != '.'))
00369           outp = tmp;
00370         else {
00371           *outp++ = '/';
00372           *outp++ = '.';
00373           *outp++ = '.';
00374         }
00375         inp+= 3;
00376       } /* if */
00377       else
00378         *outp++ = *inp++;
00379     } /* if */
00380     else
00381       *outp++ = *inp++;
00382   } /* while */
00383   
00384   *outp = '\0';
00385   return path;
00386 }
00387 
00388 #define is_absolute_file_name(file_name)        ((file_name)[0] == '/')
00389 
00390 
00391 /* Make an absolute path name from the file name,
00392  * which means no .. or . or // in the path. */
00393 extern char *
00394 Make_Absolute_Path (char *filename)
00395 {
00396    char  *normalized;
00397    INT64 cwd_length;
00398 
00399    if ( cwd == NULL ) {
00400         cwd = Get_Current_Working_Directory();
00401         cwd_size = strlen (cwd);
00402    }
00403    normalized = (char *)malloc(cwd_size+strlen(filename)+2);
00404    if (normalized == NULL) {
00405       perror("malloc");
00406       exit(RC_SYSTEM_ERROR);
00407    }
00408    if (is_absolute_file_name(filename))
00409       (void)strcpy(normalized, filename);
00410    else
00411    {
00412       cwd_length = cwd_size;
00413       strcpy(normalized, cwd);
00414       if (cwd[cwd_length - 1] != '/')
00415       {
00416          normalized[cwd_length++] = '/';
00417          normalized[cwd_length] = '\0';
00418       }
00419       (void)strcpy(&normalized[cwd_length], filename);
00420    }
00421    (void)normalize_path(normalized);
00422    return normalized;
00423 }
00424 #endif /* MONGOOSE_BE */
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Defines