diff options
author | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
---|---|---|
committer | Joe Hunkeler <jhunkeler@gmail.com> | 2015-08-11 16:51:37 -0400 |
commit | 40e5a5811c6ffce9b0974e93cdd927cbcf60c157 (patch) | |
tree | 4464880c571602d54f6ae114729bf62a89518057 /unix/boot/mkpkg/host.c | |
download | iraf-osx-40e5a5811c6ffce9b0974e93cdd927cbcf60c157.tar.gz |
Repatch (from linux) of OSX IRAF
Diffstat (limited to 'unix/boot/mkpkg/host.c')
-rw-r--r-- | unix/boot/mkpkg/host.c | 917 |
1 files changed, 917 insertions, 0 deletions
diff --git a/unix/boot/mkpkg/host.c b/unix/boot/mkpkg/host.c new file mode 100644 index 00000000..2f7c140b --- /dev/null +++ b/unix/boot/mkpkg/host.c @@ -0,0 +1,917 @@ +/* Copyright(c) 1986 Association of Universities for Research in Astronomy Inc. + */ + +#include <stdio.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> +#include <fcntl.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/time.h> + +#define import_spp +#define import_error +#include <iraf.h> +#include "mkpkg.h" +#include "extern.h" +#include "../bootProto.h" + +#ifdef LINUX +# undef SYSV +# undef i386 +# define GNUAR +#else +# ifdef BSD +# undef SYSV +# endif +#endif + +/* + * HOST.C -- [MACHDEP] Special host interface routines required by the MKPKG + * utility. + */ + +#define SZ_COPYBUF 4096 +#ifndef SZ_CMD +#define SZ_CMD 2048 /* max size OS command, see mkpkg.h */ +#endif +#define SZ_LIBPATH 512 /* path to library */ +#define LIBRARIAN "ar" +#define LIBTOOL "libtool" +#define LIBFLAGS "r" +#define REBUILD "ranlib" +#define XC "xc" +#define INTERRUPT SYS_XINT + +extern char *makeobj(); +extern char *vfn2osfn(); +extern char *getenv(); + +extern void fatals (char *fmt, char *arg); + +char *resolvefname(); +char *mkpath(); + +int h_updatelibrary (char *library, char *flist[], int totfiles, + char *xflags, char *irafdir); +int h_rebuildlibrary (char *library); +int h_incheck (char *file, char *dir); +int h_outcheck (char *file, char *dir, int clobber); +void h_getlibname (char *file, char *fname); +int h_xc (char *cmd); +int h_purge (char *dir); +int h_copyfile (char *oldfile, char *newfile); + +int u_fcopy (char *old, char *new); +int h_movefile (char *old, char *new); +int u_fmove (char *old, char *new ); +int add_sources (char *cmd, int maxch, char *flist[], + int totfiles, int hostnames, int *nsources); +int add_objects (char *cmd, int maxch, char *flist[], + int totfiles, int hostnames); + +char *makeobj (char *fname); +char *mkpath (char *module, char *directory, char *outstr); +char *resolvefname (char *fname); +int h_direq (char *dir1, char *dir2); + + + +/* H_UPDATELIBRARY -- Compile a list of source files and replace them in the + * host library. This is done by formatting a command for the XC compiler + * and passing it to the host system. Since XC is pretty much the same on + * all systems, this should be close to portable. Note that when we are + * called we are not necessarily in the same directory as the library, but + * we are always in the same directory as the files in the file list. + * Note also that the file list may contain object files which cannot be + * compiled, but which must be replaced in the library. + */ +int +h_updatelibrary ( + char *library, /* pathname of library */ + char *flist[], /* pointers to filename strings */ + int totfiles, /* number of files in list */ + char *xflags, /* XC compiler flags */ + char *irafdir /* iraf root directory */ +) +{ + char cmd[SZ_CMD+1], *args; + int exit_status, baderr, npass; + int nsources, nfiles, ndone, nleft; + int hostnames, status; + char libfname[SZ_PATHNAME+1]; + char *lname = NULL; + + /* Get the library file name. */ + h_getlibname (library, libfname); + lname = resolvefname(libfname); + + /* + * Compile the files. + * ------------------- + */ + if (irafdir[0]) + sprintf (cmd, "%s -r %s %s", XC, irafdir, xflags); + else + sprintf (cmd, "%s %s", XC, xflags); + + if (debug) + strcat (cmd, " -d"); + if (dbgout) + strcat (cmd, " -x"); + + /* Compute offset to the file list and initialize loop variables. + * Since the maximum command length is limited, only a few files + * are typically processed in each iteration. + */ + exit_status = OK; + baderr = NO; + args = &cmd[strlen(cmd)]; + nleft = totfiles; + ndone = 0; + + while (nleft > 0) { + /* Add as many filenames as will fit on the command line. + */ + nfiles = add_sources (cmd, SZ_CMD, &flist[ndone], nleft, + hostnames=NO, &nsources); + + /* This should not happen. + */ + if (nfiles <= 0) { + printf ("OS command overflow; cannot compile files\n"); + fflush (stdout); + exit_status = ERR; + return 0; + } + + if (verbose) { + if (nsources > 0) + printf ("%s\n", cmd); + else + printf ("file list contains only object files\n"); + fflush (stdout); + } + + if (execute && nsources > 0) + if ((status = os_cmd (cmd)) != OK) { + if (status == INTERRUPT) + fatals ("<ctrl/c> interrupt %s", library); + if (!ignore) + baderr++; + exit_status += status; + } + + /* Truncate command and repeat with the next few files. + */ + (*args) = EOS; + + ndone += nfiles; + nleft -= nfiles; + } + + /* Do not update object modules in library if a compilation error + * occurred. The object files will be left on disk and the user + * will rerun us after fixing the problem; the next time around we + * will see that the objects exist and are up to date, hence will + * not recompile them. When all have been successfully compiled + * the library will be updated. + */ + if (baderr) + return 0; + + /* + * Update the library. + * --------------------- + */ +#if defined(LINUX) || defined(BSD) || defined(MACOSX) +#if defined(MACOSX) && !defined(MACH64) + /* For FAT libraries we need to use libtool to update. + */ + if (access (lname, F_OK) == 0) + sprintf (cmd, "%s %s %s %s", LIBTOOL, "-a -T -o", lname, lname); + else + sprintf (cmd, "%s %s %s ", LIBTOOL, "-a -T -o", lname); +#else + sprintf (cmd, "%s %s %s", LIBRARIAN, LIBFLAGS, resolvefname(libfname)); +#endif +#else + sprintf (cmd, "%s %s %s", LIBRARIAN, LIBFLAGS, libfname); +#endif + + /* Compute offset to the file list and initialize loop variables. + * Since the maximum command length is limited, only a few files + * are typically processed in each iteration. + */ + args = &cmd[strlen(cmd)]; + nleft = totfiles; + ndone = 0; + + for (npass=0; nleft > 0; npass++) { + +#if defined(MACOSX) && !defined(MACH64) + if (npass > 0) { + /* For FAT libraries we need to use libtool to update. + */ + if (access (lname, F_OK) == 0) + sprintf (cmd, "%s %s %s %s", LIBTOOL, "-a -T -o", + lname, lname); + else + sprintf (cmd, "%s %s %s ", LIBTOOL, "-a -T -o", lname); + } +#endif + + /* Add as many filenames as will fit on the command line. */ + nfiles = add_objects (cmd, SZ_CMD, &flist[ndone], nleft, + hostnames=NO); + + /* This should not happen. */ + if (nfiles <= 0) { + printf ("OS command overflow; cannot update library `%s'\n", + libfname); + fflush (stdout); + exit_status = ERR; + return 0; + } + + if (verbose) { + printf ("%s\n", cmd); + fflush (stdout); + } + + if (execute) { + if ((exit_status = os_cmd (cmd)) == OK) { + /* Delete the object files. + */ + int i; + + for (i=0; i < nfiles; i++) + os_delete (makeobj (flist[ndone+i])); + } else if (exit_status == INTERRUPT) + fatals ("<ctrl/c> interrupt %s", library); + } + + /* Truncate command and repeat with the next few files. + */ + (*args) = EOS; + + ndone += nfiles; + nleft -= nfiles; + +#if defined(MACOSX) && !defined(MACH64) + h_rebuildlibrary (lname); +#endif + } + + return (exit_status); +} + + +/* H_REBUILDLIBRARY -- Called after all recently recompiled modules have been + * replaced in the library. When we are called we are in the same directory + * as the library. + */ +int +h_rebuildlibrary ( + char *library /* filename of library */ +) +{ +#ifdef SYSV + /* Skip the library rebuild if COFF format library. */ + return (OK); +#else + char cmd[SZ_LINE+1]; + char libfname[SZ_PATHNAME+1]; + char *libpath; + + /* Get the library file name. */ + h_getlibname (library, libfname); + libpath = resolvefname (vfn2osfn(libfname,0)); + + sprintf (cmd, "%s %s", REBUILD, libpath); + if (verbose) { + printf ("%s\n", cmd); + fflush (stdout); + } + + if (execute) + return (os_cmd (cmd)); + else + return (OK); +#endif +} + + +/* H_INCHECK -- Check a file, e.g., a library, back into the directory it + * was originally checked out from. If the directory name pointer is NULL + * merely delete the checked out copy of the file. On a UNIX system the + * checked out file is a symbolic link, so all we do is delete the link. + * On a VMS system the checked out file is a copy, and we have to physically + * copy the new file back, creating a new version of the original file. + */ +int +h_incheck ( + char *file, /* file to be checked in */ + char *dir /* where to put the file */ +) +{ + char backup[SZ_PATHNAME+1]; + char path[SZ_PATHNAME+1]; + char fname[SZ_PATHNAME+1]; + char *osfn, *ip; + struct stat fi; + int status; + + /* Get the library file name. */ + h_getlibname (file, fname); + osfn = vfn2osfn (fname, 0); + + if (verbose) { + printf ("check file `%s' into `%s'\n", fname, dir ? dir : ""); + fflush (stdout); + } + + if (stat (osfn, &fi) == ERR) { + printf ("$checkin: file `%s' not found\n", osfn); + fflush (stdout); + return (ERR); + } + + /* If the file is not a symbolic link to an existing remote file it + * is probably a new library, so move it to the destination directory, + * otherwise just delete the link. If the named file exists in + * IRAFULIB update that version of the file instead of the standard one. + */ + if (dir != NULL && !(fi.st_mode & S_IFLNK)) { + path[0] = EOS; + if ((ip = getenv("IRAFULIB"))) + if (access (mkpath(fname,ip,path), 0) < 0) + path[0] = EOS; + + if (path[0] == EOS) + status = h_movefile (osfn, mkpath(fname,dir,path)); + else + status = h_movefile (osfn, path); + + } else + status = unlink (osfn); + + /* If there was a local copy of the file it will have been renamed + * with a .cko extension when the file was checked out, and should be + * restored. + */ + sprintf (backup, "%s.cko", fname); + if (access (backup, 0) == 0) { + if (debug) { + printf ("h_incheck: rename %s -> %s\n", backup, fname); + fflush (stdout); + } + if (rename (backup, fname) == -1) + printf ("cannot rename %s -> %s\n", backup, fname); + } + + return (status); +} + + +/* H_OUTCHECK -- Check out a file, e.g., gain access to a library in the + * current directory so that it can be updated. If the file has already + * been checked out do not check it out again. In principle we should also + * place some sort of a lock on the file while it is checked out, but... + */ +int +h_outcheck ( + char *file, /* file to be checked out */ + char *dir, /* where to get the file */ + int clobber /* clobber existing copy of file? */ +) +{ + register char *ip, *op; + char path[SZ_PATHNAME+1]; + char fname[SZ_PATHNAME+1]; + + /* Get the library file name. */ + h_getlibname (file, fname); + + /* Make the UNIX pathname of the destination file. [MACHDEP] + * Use the IRAFULIB version of the file if there is one. + */ + path[0] = EOS; + if ((ip = getenv("IRAFULIB"))) + if (access (mkpath(fname,ip,path), 0) < 0) + path[0] = EOS; + + if (path[0] == EOS) { + for (ip=vfn2osfn(dir,0), op=path; (*op = *ip++); op++) + ; + if (*(op-1) != '/') + *op++ = '/'; + for (ip=vfn2osfn(fname,0); (*op = *ip++); op++) + ; + *op = EOS; + } + + if (verbose) { + printf ("check out file `%s = %s'\n", fname, path); + fflush (stdout); + } + + /* If the file already exists and clobber is enabled, delete it. + * If the file is a symbolic link (a pathname), and IRAF has been + * moved since the link was created, then the symlink will be + * pointing off into never never land and must be redone. If clobber + * is NOT enabled, then probably the remote copy of the file is an + * alternate source for the local file, which must be preserved. + */ + if (access (fname, 0) != -1) { + char backup[SZ_PATHNAME+1]; + + if (clobber) { + if (debug) { + printf ("h_outcheck: deleting %s\n", fname); + fflush (stdout); + } + unlink (fname); + } else { + /* Do not rename the file twice; if the .cko file already + * exists, the second time would clobber it. Note that if a + * mkpkg run is aborted, the checked out file and renamed + * local file will remain, but a subsequent successful mkpkg + * will restore everything. + */ + sprintf (backup, "%s.cko", fname); + if (access (backup, 0) == -1) { + if (debug) { + printf ("h_outcheck: rename %s -> %s\n", fname, backup); + fflush (stdout); + } + if (rename (fname, backup) == -1) + printf ("cannot rename %s -> %s\n", fname, backup); + } + } + } + + return (symlink (path, fname)); +} + + +/* H_GETLIBNAME -- Get a library filename. If debug output is enabled (-g + * or -x), and we are checking out a library file (.a), update the debug + * version of the library (XX_p.a). + */ +void +h_getlibname ( + char *file, + char *fname +) +{ + register char *ip; + + strcpy (fname, file); + if (dbgout) { + for (ip=fname; *ip; ip++) + ; + if (*(ip-2) == '.' && *(ip-1) == 'a' && + !(*(ip-4) == '_' && *(ip-3) == 'p')) { + *(ip-2) = '_'; + *(ip-1) = 'p'; + *(ip-0) = '.'; + *(ip+1) = 'a'; + *(ip+2) = '\0'; + } + } +} + + +/* H_XC -- Host interface to the XC compiler. On UNIX all we do is use the + * oscmd facility to pass the XC command line on to UNIX. + */ +int +h_xc (char *cmd) +{ + return (os_cmd (cmd)); +} + + +/* H_PURGE -- Purge all old versions of all files in the named directory. + * This is a no-op on UNIX since multiple file versions are not supported. + */ +int +h_purge ( + char *dir /* LOGICAL directory name */ +) +{ + if (verbose) { + printf ("purge directory `%s'\n", dir); + fflush (stdout); + } + + /* + * format command "purge [dir]*.*;*" + * if (verbose) + * echo command to stdout + * if (execute) + * call os_cmd to execute purge command + */ + + return (OK); +} + + +/* H_COPYFILE -- Copy a file. If the new file already exists it is + * clobbered (updated). + */ +int +h_copyfile ( + char *oldfile, /* existing file to be copied */ + char *newfile /* new file, not a directory name */ +) +{ + char old[SZ_PATHNAME+1]; + char new[SZ_PATHNAME+1]; + + strcpy (old, vfn2osfn (oldfile, 0)); + strcpy (new, vfn2osfn (newfile, 1)); + + if (verbose) { + printf ("copy %s to %s\n", old, new); + fflush (stdout); + } + + if (execute) { + if (os_access (old, 0,0) == NO) { + printf ("$copy: file `%s' not found\n", oldfile); + fflush (stdout); + return (ERR); + } else + return (u_fcopy (old, new)); + } + + return (OK); +} + + +/* U_FCOPY -- Copy a file, UNIX. + */ +int +u_fcopy ( + char *old, + char *new +) +{ + char buf[SZ_COPYBUF], *ip; + int in, out, nbytes; + struct stat fi; + long totbytes; + + /* Open the old file and create the new one with the same mode bits + * as the original. + */ + if ((in = open(old,0)) == ERR || fstat(in,&fi) == ERR) { + printf ("$copy: cannot open input file `%s'\n", old); + fflush (stdout); + return (ERR); + } if ((out = creat(new,0644)) == ERR || fchmod(out,fi.st_mode) == ERR) { + printf ("$copy: cannot create output file `%s'\n", new); + fflush (stdout); + close (in); + return (ERR); + } + + /* Copy the file. + */ + totbytes = 0; + while ((nbytes = read (in, buf, SZ_COPYBUF)) > 0) + if (write (out, buf, nbytes) == ERR) { + close (in); close (out); + printf ("$copy: file write error on `%s'\n", new); + fflush (stdout); + return (ERR); + } else + totbytes += nbytes; + + close (in); + close (out); + + /* Check for premature termination of the copy. + */ + if (totbytes != fi.st_size) { + printf ("$copy: file changed size `%s' oldsize=%d, newsize=%d\n", + old, (int)fi.st_size, (int)totbytes); + fflush (stdout); + return (ERR); + } + + /* If file is a library (".a" extension in UNIX), preserve the + * modify date else UNIX will think the library symbol table is + * out of date. + */ + for (ip=old; *ip; ip++) + ; + ip -= 2; + if (ip > old && strcmp (ip, ".a") == 0) { + struct timeval tv[2]; + + tv[0].tv_sec = fi.st_atime; + tv[1].tv_sec = fi.st_mtime; + utimes (new, tv); + } + + return (OK); +} + + +/* H_MOVEFILE -- Move a file from the current directory to another directory, + * or rename the file within the current directory. If the destination file + * already exists it is clobbered. + */ +int +h_movefile ( + char *old, /* file to be moved */ + char *new /* new pathname of file */ +) +{ + char old_osfn[SZ_PATHNAME+1]; + char new_osfn[SZ_PATHNAME+1]; + + strcpy (old_osfn, vfn2osfn (old, 0)); + strcpy (new_osfn, vfn2osfn (new, 0)); + + if (debug) { + printf ("move %s to %s\n", old_osfn, new_osfn); + fflush (stdout); + } + + if (execute) { + if (os_access (old_osfn, 0,0) == NO) { + printf ("$move: file `%s' not found\n", old); + fflush (stdout); + return (ERR); + } else + return (u_fmove (old_osfn, new_osfn)); + } + + return (OK); +} + + +/* U_FMOVE -- Unix procedure to move or rename a file. Will move file to a + * different device (via a file copy) if necessary. + */ +int +u_fmove ( + char *old, + char *new +) +{ + unlink (new); + if (link (old, new) == ERR) + if (u_fcopy (old, new) == ERR) { + printf ("$move: cannot create `%s'\n", new); + fflush (stdout); + return (ERR); + } + + if (unlink (old) == ERR) { + printf ("$move: cannot unlink `%s'\n", old); + fflush (stdout); + return (ERR); + } + + return (OK); +} + + +/* ADD_SOURCES -- Append source files from the file list to the command + * buffer. Omit object files. Return a count of the number of files to + * be compiled. This code is machine dependent since Unix permits arbitrarily + * long command lines, but most systems do not, in which case something + * else must be done (e.g., write a command file and have the host system + * process that). + */ +int +add_sources ( + char *cmd, /* concatenate to this */ + int maxch, /* max chars out */ + char *flist[], /* pointers to filename strings */ + int totfiles, /* number of files in list */ + int hostnames, /* return host filenames? */ + int *nsources /* receives number of src files */ +) +{ + register char *ip, *op, *otop; + register int i; + int nfiles; + + *nsources = 0; + nfiles = 0; + + otop = &cmd[maxch]; + for (op=cmd; *op; op++) + ; + + for (i=0; i < totfiles; i++) { + /* Skip over object files. + */ + for (ip=flist[i]; *ip; ip++) + ; + if (strcmp (ip-2, ".o") == 0) { + nfiles++; + continue; + } + + if (op + strlen (flist[i]) + 1 >= otop) + break; + + nfiles++; + (*nsources)++; + *op++ = ' '; + + if (hostnames) + ip = vfn2osfn (flist[i], 0); + else + ip = flist[i]; + + for (; (*op = *ip++); op++) + ; + } + + return (nfiles); +} + + +/* ADD_OBJECTS -- Append the ".o" equivalent of each file name to the + * output command buffer. Return the number of file names appended. + */ +int +add_objects ( + char *cmd, /* concatenate to this */ + int maxch, /* max chars out */ + char *flist[], /* pointers to filename strings */ + int totfiles, /* number of files in list */ + int hostnames /* return host filenames? */ +) +{ + register char *ip, *op, *otop; + register int i; + int nfiles; + + otop = &cmd[maxch]; + for (op=cmd; *op; op++) + ; + + for (i=0, nfiles=0; i < totfiles; i++) { + if (op + strlen (flist[i]) + 1 >= otop) + break; + + nfiles++; + *op++ = ' '; + + ip = makeobj (flist[i]); + if (hostnames) + ip = vfn2osfn (ip,0); + + for (; (*op = *ip++); op++) + ; + } + + return (nfiles); +} + + +/* MAKEOBJ -- Return a pointer to the ".o" equivalent of the input file + * name. The last period in the input filename is assumed to delimit the + * filename extension. + */ +char * +makeobj (char *fname) +{ + register char *ip, *op; + static char objfile[SZ_FNAME+1]; + char *lastdot; + + for (ip=fname, op=objfile, lastdot=NULL; (*op = *ip++); op++) + if (*op == '.') + lastdot = op; + + if (lastdot != NULL) + op = lastdot; + strcpy (op, ".o"); + + return (objfile); +} + + +/* MKPATH -- Given a module name and a directory name, return the pathname of + * the module in the output string. Do not use the directory pathname if the + * module name is already a pathname. + */ +char * +mkpath ( + char *module, + char *directory, + char *outstr +) +{ + register char *ip, *op; + + if (directory && module[0] != '/') { + for (ip=directory, op=outstr; (*op = *ip++); op++) + ; + if (op > outstr && *(op-1) != '/') { + *op++ = '/'; + *op = EOS; + } + for (ip=module; (*op = *ip++); op++) + ; + } else + strcpy (outstr, module); + + return (outstr); +} + + +/* RESOLVEFNAME -- If a filename reference is a symbolic link resolve it to + * the pathname of an actual file by tracing back through all symbolic links + * to the fully resolved file or path. + * + * Example: + * + * ./libsys.a -> /iraf/iraf/lib/libsys.a + * /iraf/iraf/lib/libsys.a -> ../bin/libsys.a + * -> /iraf/iraf/bin/libsys.a + * + * Note that the "fully resolved" filename may still contain unresolved links + * for directory elements - it is only the filename which is fully resolved + * in the output pathname. + */ +char * +resolvefname (char *fname) +{ + static char pathname[SZ_LIBPATH]; + char relpath[SZ_LIBPATH]; + extern char *strrchr(); + + strcpy (pathname, fname); + while (os_symlink (pathname, relpath, SZ_LIBPATH)) { + if (relpath[0] == '/') { + /* Link to an absolute pathname, just use new path. */ + strcpy (pathname, relpath); + } else { + /* Relative path. This includes upwards references such + * as ../foo. Replace the filename by the relative path. + * Let unix resolve any upwards references later, when the + * file is accessed. + */ + char *str = strrchr(pathname,'/'); + strcpy ((str ? (str+1) : pathname), relpath); + } + } + + return (pathname); +} + + +/* H_DIREQ -- Compare two directory pathnames for equality. This is easy + * in most cases, but the comparison can fail when it shouldn't due to aliases + * for directory names, e.g., a directory may be referred to by a symbolic + * name, but get-cwd will return a different path, causing the comparison to + * fail. + */ +int +h_direq (char *dir1, char *dir2) +{ + register char *ip1, *ip2; + + /* If the pathname contains a directory named "irafXXX" (where the + * XXX are optional characters in the directory name) everything to + * the left for the purposes of this comparision. This allows the + * iraf root directory to be specified with a path such as + * + * /<whatever>/iraf/iraf.version/ + * + * and the directory name comparision will take place using only + * the portion of the path following this prefix. + */ + for (ip1=dir1; *ip1; ip1++) + if (*ip1 == '/' && *(ip1+1) == 'i') + if (strncmp (ip1+1, "iraf", 4) == 0) { + for (ip1++; *ip1 && *ip1 != '/'; ip1++) + ; + if (*ip1 == '/') + dir1 = ip1 + 1; + --ip1; + } + for (ip2=dir2; *ip2; ip2++) + if (*ip2 == '/' && *(ip2+1) == 'i') + if (strncmp (ip2+1, "iraf", 4) == 0) { + for (ip2++; *ip2 && *ip2 != '/'; ip2++) + ; + if (*ip2 == '/') + dir2 = ip2 + 1; + --ip2; + } + + return (strcmp (dir1, dir2) == 0); +} |