Commit 2a9f2bb9 by Richard Kenner

Initial revision

From-SVN: r10337
parent 929e7d86
/*
* @(#)msd_dir.c 1.4 87/11/06 Public Domain.
*
* A public domain implementation of BSD directory routines for
* MS-DOS. Written by Michael Rendell ({uunet,utai}michael@garfield),
* August 1897
*
* Modified by Ian Stewartson, Data Logic (istewart@datlog.co.uk).
*
* Updates: 1. To support OS/2 1.x
* 2. To support HPFS long filenames
* 3. To support OS/2 2.x
* 4. To support TurboC
* 5. To support Windows NT
*/
#include <sys/types.h>
#include <sys/stat.h>
#include <stdio.h>
#include <stdlib.h>
#include <malloc.h>
#include <string.h>
#include <limits.h>
#include <ctype.h>
#include <errno.h>
#include <dirent.h>
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#define FILE_NAME_E cFileName
#define OS_CloseFH(a) FindClose (a)
#define FIND_BUFFER WIN32_FIND_DATA
#define DISABLE_HARD_ERRORS SetErrorMode (0)
#define ENABLE_HARD_ERRORS SetErrorMode (SEM_FAILCRITICALERRORS | \
SEM_NOOPENFILEERRORBOX);
# define ERROR_EMPTY_DIR ERROR_FILE_NOT_FOUND
# define ATTRIBUTES (_A_SUBDIR | _A_HIDDEN | _A_SYSTEM | \
_A_NORMAL | _A_RDONLY | _A_ARCH)
/*
* missing ??
*/
#ifndef ENOTDIR
# define ENOTDIR 120 /* Not a directory */
#endif
#ifndef S_IFMT
# define S_IFMT 0xf000 /* type of file */
#endif
#ifndef S_ISDIR
# define S_ISDIR(m) ((((m) & S_IFMT) == S_IFDIR))
#endif
/*
* Internals
*/
typedef struct _dircontents DIRCONT;
static void free_dircontents (DIRCONT *);
/*
* Open the directory stream
*/
DIR *
opendir (name)
const char *name;
{
struct stat statb;
DIR *dirp;
char *last;
DIRCONT *dp;
char *nbuf;
int len = strlen (name);
unsigned long rc;
FIND_BUFFER dtabuf;
HANDLE d_handle;
bool HPFS = FALSE;
if (!len)
{
errno = ENOTDIR;
return (DIR *)NULL;
}
if ((nbuf = malloc (len + 5)) == (char *)NULL)
return (DIR *) NULL;
strcpy (nbuf, name);
last = &nbuf[len - 1];
/* Ok, DOS is very picky about its directory names. The following are
* valid.
*
* c:/
* c:.
* c:name/name1
*
* c:name/ is not valid
*/
if (((*last == '\\') || (*last == '/')) && (len > 1) &&
(!((len == 3) && (name[1] == ':'))))
*(last--) = 0;
/* Check its a directory */
DISABLE_HARD_ERRORS;
rc = stat (nbuf, &statb);
ENABLE_HARD_ERRORS;
if (rc)
{
free (nbuf);
return (DIR *) NULL;
}
if (!S_ISDIR (statb.st_mode))
{
free (nbuf);
errno = ENOTDIR;
return (DIR *)NULL;
}
if ((dirp = (DIR *) malloc (sizeof (DIR))) == (DIR *) NULL)
{
free (nbuf);
return (DIR *) NULL;
}
/* Set up to find everything */
if ((*last != '\\') && (*last != '/'))
strcat (last, "/");
strcat (last, "*.*");
/* Find the file system type */
HPFS = IsHPFSFileSystem (nbuf);
dirp->dd_loc = 0;
dirp->dd_cp = (DIRCONT *) NULL;
dirp->dd_contents = (DIRCONT *) NULL;
DISABLE_HARD_ERRORS;
d_handle = FindFirstFile (nbuf, &dtabuf);
rc = (d_handle == INVALID_HANDLE_VALUE) ? GetLastError () : 0;
ENABLE_HARD_ERRORS;
/* Check for errors */
if (rc)
{
free (nbuf);
/* Empty directory */
#if defined (ERROR_EMPTY_DIR)
if (rc == ERROR_EMPTY_DIR)
return dirp;
#endif
free (dirp);
return (DIR *) NULL;
}
/* Process the directory */
do
{
if (((dp = (DIRCONT *) malloc (sizeof (DIRCONT))) == (DIRCONT *)NULL) ||
((dp->_d_entry = strdup (dtabuf.FILE_NAME_E)) == (char *) NULL))
{
if (dp->_d_entry != (char *)NULL)
free ((char *)dp);
free (nbuf);
free_dircontents (dirp->dd_contents);
OS_CloseFH (d_handle);
return (DIR *) NULL;
}
if (!HPFS)
strlwr (dp->_d_entry);
if (dirp->dd_contents != (DIRCONT *) NULL)
dirp->dd_cp = dirp->dd_cp->_d_next = dp;
else
dirp->dd_contents = dirp->dd_cp = dp;
dp->_d_next = (DIRCONT *) NULL;
} while (FindNextFile (d_handle, &dtabuf));
dirp->dd_cp = dirp->dd_contents;
free (nbuf);
OS_CloseFH (d_handle);
return dirp;
}
/*
* Close the directory stream
*/
int
closedir (dirp)
DIR *dirp;
{
if (dirp != (DIR *)NULL)
{
free_dircontents (dirp->dd_contents);
free ((char *)dirp);
}
return 0;
}
/*
* Read the next record from the stream
*/
struct dirent *
readdir (dirp)
DIR *dirp;
{
static struct dirent dp;
if ((dirp == (DIR *)NULL) || (dirp->dd_cp == (DIRCONT *) NULL))
return (struct dirent *) NULL;
dp.d_reclen = strlen (strcpy (dp.d_name, dirp->dd_cp->_d_entry));
dp.d_off = dirp->dd_loc * 32;
dp.d_ino = (ino_t)++dirp->dd_loc;
dirp->dd_cp = dirp->dd_cp->_d_next;
return &dp;
}
/*
* Restart the directory stream
*/
void
rewinddir (dirp)
DIR *dirp;
{
seekdir (dirp, (off_t)0);
}
/*
* Move to a know position in the stream
*/
void
seekdir (dirp, off)
DIR *dirp;
off_t off;
{
long i = off;
DIRCONT *dp;
if ((dirp == (DIR *)NULL) || (off < 0L))
return;
for (dp = dirp->dd_contents; (--i >= 0) && (dp != (DIRCONT *)NULL);
dp = dp->_d_next)
;
dirp->dd_loc = off - (i + 1);
dirp->dd_cp = dp;
}
/*
* Get the current position
*/
off_t
telldir(dirp)
DIR *dirp;
{
return (dirp == (DIR *)NULL) ? (off_t) -1 : dirp->dd_loc;
}
/*
* Release the internal structure
*/
static void
free_dircontents (dp)
DIRCONT *dp;
{
DIRCONT *odp;
while ((odp = dp) != (DIRCONT *)NULL)
{
if (dp->_d_entry != (char *)NULL)
free (dp->_d_entry);
dp = dp->_d_next;
free ((char *)odp);
}
}
/*
* Windows NT version
*/
bool
IsHPFSFileSystem (directory)
char *directory;
{
char bName[4];
DWORD flags;
DWORD maxname;
BOOL rc;
unsigned int nDrive;
char szCurDir [MAX_PATH];
if (isalpha (directory[0]) && (directory[1] == ':'))
nDrive = toupper (directory[0]) - '@';
else
{
GetCurrentDirectory (MAX_PATH, szCurDir);
nDrive = szCurDir[0] - 'A' + 1;
}
/* Set up the drive name */
strcpy (bName, "x:\\");
bName[0] = (char) (nDrive + '@');
/* Read the volume info, if we fail - assume non-HPFS */
DISABLE_HARD_ERRORS;
rc = GetVolumeInformation (bName, (LPTSTR)NULL, 0, (LPDWORD)NULL,
&maxname, &flags, (LPTSTR)NULL, 0);
ENABLE_HARD_ERRORS;
return ((rc) && (flags & (FS_CASE_SENSITIVE | FS_CASE_IS_PRESERVED)))
? TRUE : FALSE;
}
/*
* dirent.h
*/
#ifndef _DIRENT_H
# define _DIRENT_H
# include <sys/types.h>
# include <limits.h>
#define MAXNAMLEN 255 /* maximum filename length */
#ifndef NAME_MAX
#define NAME_MAX (MAXNAMLEN - 1)
#endif
struct dirent /* data from getdents()/readdir() */
{
ino_t d_ino; /* inode number of entry */
off_t d_off; /* offset of disk directory entry */
wchar_t d_reclen; /* length of this record */
char d_name[MAXNAMLEN + 1];
};
/* The following nonportable ugliness could have been avoided by defining
* DIRENTSIZ and DIRENTBASESIZ to also have (struct dirent *) arguments.
* There shouldn't be any problem if you avoid using the DIRENTSIZ() macro.
*/
#define DIRENTBASESIZ (((struct dirent *)0)->d_name \
- (char *)&((struct dirent *)0)->d_ino)
#define DIRENTSIZ(namlen) ((DIRENTBASESIZ + sizeof(long) + (namlen)) \
/ sizeof(long) * sizeof(long))
# ifndef _BOOL_T_DEFINED
typedef unsigned char bool;
# define _BOOL_T_DEFINED
# endif
# define DIRBUF 8192 /* buffer size for fs-indep. dirs */
/* must in general be larger than the */
/* filesystem buffer size */
struct _dircontents {
char *_d_entry;
struct _dircontents *_d_next;
};
typedef struct _dirdesc {
int dd_id; /* uniquely identify each open directory */
long dd_loc; /* where we are in directory entry is this */
struct _dircontents *dd_contents; /* pointer to contents of dir */
struct _dircontents *dd_cp; /* pointer to current position */
} DIR;
#if defined (__STDC__)
# define _PROTO(p) p
#else
# define _PROTO(p) ()
# undef const
# undef volatile
#endif
/* Functions */
extern DIR * opendir _PROTO ((const char *));
extern struct dirent * readdir _PROTO ((DIR *));
extern void rewinddir _PROTO ((DIR *));
extern int closedir _PROTO ((DIR *));
extern void seekdir _PROTO ((DIR *, off_t));
extern off_t telldir _PROTO ((DIR *));
extern int chdir _PROTO ((const char *));
extern char * getcwd _PROTO ((char *, size_t));
extern int mkdir _PROTO ((const char *));
extern int rmdir _PROTO ((const char *));
extern int scandir _PROTO ((char *,
struct dirent ***,
int (*)(const void *, const void *),
int (*)(const void *, const void *)));
extern int _chdrive _PROTO ((int));
extern int _getdrive _PROTO ((void));
extern char * _getdcwd _PROTO ((int, char *, int));
extern bool IsHPFSFileSystem _PROTO ((char *));
#endif
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <dirent.h>
#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <process.h>
static char *concat();
static char *concat3();
static char *concat4();
static int onlyonedir;
static int atleastone;
static char *fixeddirs, *origdirs;
/* Convert all /'s to \'s */
char *
slash2slash (dirname)
char *dirname;
{
int i;
for (i=0; dirname[i]; i++)
if (dirname [i] == '/')
dirname [i] = '\\';
return dirname;
}
/* Examine each directory component of a path and create the directory */
int
mkdirpath (dirpath)
char *dirpath;
{
char *ndirpath = strdup (dirpath);
char *bp, *fp;
fp = bp = ndirpath;
while (bp)
{
bp = strchr (fp, '\\');
if (bp)
{
*bp = 0;
_mkdir (ndirpath);
*bp = '\\';
fp = ++bp;
}
else
_mkdir (ndirpath);
}
}
/* Construct a relative directory path from a given path by removing the
leading slash, if it exists and changing a drive letter from X: to X-. */
char *
newname (olddirname)
char *olddirname;
{
char *newname = strdup (olddirname);
if ((strlen (newname) >= 2)
&& (isalpha (newname[0]) && newname[1] == ':'))
newname [1] = '-';
else if ((strlen (newname) >= 1)
&& (newname [0] == '/' || newname [0] == '\\'))
newname = &newname[1];
return newname;
}
/* Run the sed script on one header file. If no modifications were made, then
delete the newly created file. */
int
doheader (oneheader, outheader, oldsize)
char *oneheader, *outheader;
int oldsize;
{
char *newbuff, *oldbuff;
char *newheader = concat3 ("include", "\\", newname (outheader));
struct _stat newstatbuf;
int newdesc, olddesc;
int i;
system (concat4 ("sed -f fixinc-nt.sed ", oneheader, " > ", newheader));
_stat (newheader, &newstatbuf);
if (oldsize != newstatbuf.st_size)
{
atleastone = 1;
printf ("Fixing: %s\n", oneheader);
return 0;
}
oldbuff = malloc (oldsize);
newbuff = malloc (newstatbuf.st_size);
olddesc = open (oneheader, _O_RDONLY | _O_BINARY);
newdesc = open (newheader, _O_RDONLY | _O_BINARY);
read (olddesc, oldbuff, oldsize);
read (newdesc, newbuff, newstatbuf.st_size);
close (olddesc);
close (newdesc);
for (i=0; i<oldsize; i++)
{
if (oldbuff [i] != newbuff [i])
{
free (oldbuff);
free (newbuff);
atleastone = 1;
printf ("Fixing: %s\n", oneheader);
return 0;
}
}
free (oldbuff);
free (newbuff);
unlink (newheader);
return 0;
}
/* Examine the contents of a directory and call doheader () for a regular file
and recursively call dodir () for an enclosed directory. */
int
dodir (indir, outdir)
char *indir, *outdir;
{
DIR *dir;
struct dirent *dire;
struct _stat statbuf;
char *intempbuf, *outtempbuf;
dir = opendir (indir);
if (!dir) return 0;
mkdirpath (concat3 ("include", "\\", newname (outdir)));
while ((dire = readdir (dir)))
{
if (dire->d_name[0] == '.')
continue;
intempbuf = slash2slash (concat3 (indir, "\\", dire->d_name));
outtempbuf = slash2slash (concat3 (outdir, "\\", dire->d_name));
_stat (intempbuf, &statbuf);
/* If directory ... */
if (statbuf.st_mode & _S_IFDIR)
dodir (intempbuf, outtempbuf);
/* If regular file ... */
if (statbuf.st_mode & _S_IFREG)
doheader (intempbuf, outtempbuf, statbuf.st_size);
}
closedir (dir);
return 0;
}
/* Retrieve the value of the Include environment variable, copy it into a
temporary and append a semi-colon for book-keeping purposes. Then call
dodir () for each complete directory that is named therein. If there is
only one directory, then direct the output to use include\. as the
root instead of include/<directory path>, where <directory path> is a path
constructed from the path named in the Include environment variable.
I.e. if Include=C:\MSTOOLS\Include;D:\MSVC20\Include then the modified
header files will be in include\C-\MSTOOLS\Include and
include\D-\MSVC20\Include. However if Include=C:\MSTOOLS\Include then the
modified files will be in include\. */
int
main ()
{
char *fp, *bp, *foobar;
char *incvar = getenv ("Include");
int varlen = 0;
struct _stat statbuf;
if (incvar == NULL) return 0;
varlen = strlen (incvar);
foobar = (char *) malloc (varlen + 2);
strcpy (foobar, incvar);
foobar = slash2slash (foobar);
if (foobar [varlen-1] != ';') strcat (foobar, ";");
fp = bp = foobar;
if (strchr (fp, ';') == strrchr (fp, ';'))
onlyonedir = 1;
else
onlyonedir = 0;
fixeddirs = strdup(".\\include");
origdirs = strdup("");
while (bp)
{
bp = strchr (fp, ';');
if (bp)
{
*bp = 0;
_stat (fp, &statbuf);
if (statbuf.st_mode & _S_IFDIR)
{
atleastone = 0;
if (onlyonedir)
dodir (fp, ".");
else
dodir (fp, fp);
if (atleastone && !onlyonedir)
{
origdirs = concat3 (origdirs, ";", fp);
fixeddirs = concat3 (fixeddirs, ";",
concat3 (".\\include", "\\", newname(fp)));
}
}
fp = ++bp;
}
}
printf ("set C_Include_Path=%s%s\n", fixeddirs, origdirs);
return 0;
}
/* Utility function that mallocs space and concatenates two strings. */
static char *
concat (s1, s2)
char *s1, *s2;
{
int len1 = strlen (s1);
int len2 = strlen (s2);
char *result = malloc (len1 + len2 + 1);
strcpy (result, s1);
strcpy (result + len1, s2);
*(result + len1 + len2) = 0;
return result;
}
/* Utility function that concatenates three strings. */
static char *
concat3 (s1, s2, s3)
char *s1, *s2, *s3;
{
return concat (concat (s1, s2), s3);
}
/* Utility function that concatenates four strings. */
static char *
concat4 (s1, s2, s3, s4)
char *s1, *s2, *s3, *s4;
{
return concat (concat (s1, s2), concat (s3, s4));
}
# Build the include directory. The stamp files are stmp-* rather than
# stamp-* so that mostlyclean does not force the include directory to
# be rebuilt.
# Copy in the headers provided with gcc.
USER_H = $(srcdir)\ginclude\stdarg.h $(srcdir)\ginclude\stddef.h \
$(srcdir)\ginclude\varargs.h $(srcdir)\ginclude\va-alpha.h \
$(srcdir)\ginclude\va-h8300.h $(srcdir)\ginclude\va-i860.h \
$(srcdir)\ginclude\va-i960.h $(srcdir)\ginclude\va-mips.h \
$(srcdir)\ginclude\va-m88k.h $(srcdir)\ginclude\va-pa.h \
$(srcdir)\ginclude\va-pyr.h $(srcdir)\ginclude\va-sparc.h \
$(srcdir)\ginclude\va-clipper.h $(srcdir)\ginclude\va-spur.h \
$(srcdir)\ginclude\iso646.h \
$(srcdir)\ginclude\proto.h
# Build the include directory except for float.h (which depends upon
# enquire).
stmp-int-hdrs: $(USER_H)
type $(srcdir)\limitx.h >xlimits.h
type $(srcdir)\glimits.h >>xlimits.h
type $(srcdir)\limity.h >>xlimits.h
-mkdir include
for %%f in ($(USER_H)) do copy %%f include
del include\limits.h
copy xlimits.h include\limits.h
del include\syslimits.h
copy $(srcdir)\gsyslimits.h include\syslimits.h
copy include\limits.h include\syslimits.h
del include\README
copy $(srcdir)\README-fixinc include\README
touch stmp-int-hdrs
stmp-headers: stmp-int-hdrs fixinc-nt.exe
fixinc-nt
touch stmp-headers
# Build float.h.
stmp-float_h: libgcc.lib enquire.exe
-.\enquire -f > tmp-float.h
del include\float.h
copy tmp-float.h include\float.h
touch stmp-float_h
fixinc-nt.obj: $(srcdir)/config/winnt/fixinc-nt.c
cl -c -I. -I$(srcdir) -I$(srcdir)/include $(srcdir)/config/winnt/fixinc-nt.c
fixinc-nt.exe: fixinc-nt.obj dirent.obj
cl fixinc-nt.obj dirent.obj libc.lib kernel32.lib
# Build libgcc.a
libgcc.lib : libgcc1.c libgcc2.c mklibgcc.exe
mklibgcc -c
mklibgcc "cl -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES)" libgcc1.c $(LIB1FUNCS)
mklibgcc "xgcc -B./ -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES)" libgcc2.c $(LIB2FUNCS)
mklibnow.bat
-del libgcc.lib
lib -verbose -out:libgcc.lib lgcctmp/*.obj
mklibgcc.obj : $(srcdir)/config/winnt/mklibgcc.c
cl -I. -I$(srcdir) -I$(srcdir)/config/winnt -c $(srcdir)/config/winnt/mklibgcc.c
dirent.obj : $(srcdir)/config/winnt/dirent.c stmp-int-hdrs
cl -I. -I$(srcdir) -I$(srcdir)/include -I$(srcdir)/config/winnt -c $(srcdir)/config/winnt/dirent.c
mklibgcc.exe : mklibgcc.obj dirent.obj
cl mklibgcc.obj dirent.obj libc.lib kernel32.lib
#include <stdio.h>
#include <string.h>
#include <dirent.h>
char *skips[] = {
0
};
int
do_clean()
{
DIR *dir;
struct dirent *de;
remove("mklibnow.bat");
dir = opendir("lgcctmp");
if (!dir)
return 0;
while ((de=readdir(dir)))
{
char buf[30];
if (de->d_name[0] == '.')
continue;
sprintf(buf, "lgcctmp/%s", de->d_name);
unlink(buf);
}
closedir(dir);
return 0;
}
int
main(int argc, char **argv)
{
char *cc = argv[1];
char *csrc=argv[2];
int i;
FILE *batfile;
FILE *cfile;
if (argc > 1 && strcmp(argv[1], "-c")==0)
return do_clean();
_mkdir("lgcctmp", 0755);
batfile = fopen("mklibnow.bat", "a");
if (!batfile)
{
perror("mklibnow.bat");
return 1;
}
/* fprintf(batfile, "@echo off\n"); */
for (i=3; i<argc; i++)
{
char dirname[30], basename[30], fullname[30], *bp;
int s;
for (s=0; skips[s]; s++)
if (strcmp(skips[s], argv[i]) == 0)
break;
if (skips[s])
continue;
strcpy(dirname, "lgcctmp/");
strcpy(basename, "\0");
if (strncmp(argv[i], "_fix", 4)==0)
{
strcat(basename, "fx");
strcat(basename, argv[i]+4);
}
else if (strncmp(argv[i], "_float", 4)==0)
{
strcat(basename, "flt");
strcat(basename, argv[i]+6);
}
else
{
strcat(basename, argv[i]);
}
strcpy (fullname, dirname);
strcat (fullname, basename);
fprintf(batfile, "%s -c lgcctmp/%s.c\n", cc, basename);
fprintf(batfile, "copy %s.obj lgcctmp\n", basename);
bp = fullname + strlen(fullname);
strcpy(bp, ".c");
cfile = fopen(fullname, "w");
if (cfile)
{
*bp = 0;
fprintf(cfile, "#define L%s\n#include \"%s\"\n", argv[i], csrc);
fclose(cfile);
}
else
perror(fullname);
}
fclose(batfile);
return 0;
}
STMP_FIXPROTO =
OTHER_FIXINCLUDES_DIRS=${srcdir}
RANLIB = :
RANLIB_TEST = false
OLDCC = cl
MAKE = make
SHELL = sh
SYMLINK = cp
INSTALL = $(srcdir)/install.sh -c
.SUFFIXES: .obj
.c.obj:
$(CC) -c $(ALL_CFLAGS) $(ALL_CPPFLAGS) $(INCLUDES) $<
.adb.obj:
$(CC) -c $(ALL_ADAFLAGS) $<
.ads.obj:
$(CC) -c $(ALL_ADAFLAGS) $<
exeext = .exe
objext = .obj
CC = gcc
CLIB =
LDFLAGS =
ld.o: $(srcdir)/config/winnt/ld.c
$(CC) -I. -I$(srcdir) -I$(srcdir)/config -c $(srcdir)/config/winnt/ld.c
ld.exe: ld.o
$(CC) -o ld.exe ld.o
oldnames.o: $(srcdir)/config/winnt/oldnames.c
$(CC) -I. -I$(srcdir) -I$(srcdir)/config -c $(srcdir)/config/winnt/oldnames.c
spawnv.o: $(srcdir)/config/winnt/spawnv.c
$(CC) -I. -I$(srcdir) -I$(srcdir)/config -c $(srcdir)/config/winnt/spawnv.c
s/!__STDC__/!defined (__STRICT_ANSI__)/g
s/getcwd(char \*, int)/getcwd(char *, size_t)/
s/Format\[\]/Format\[1\]/
s/^#if !defined (__cplusplus)/#if 0/
s/^#define DECLSPEC_IMPORT __declspec(dllimport)/#define DECLSPEC_IMPORT/
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment