/* * dosemu.c * * UNIX function emulations for DOS */ #include #include "fd.h" #include "termio.h" #include "func.h" #ifndef O_ACCMODE #define O_ACCMODE (O_RDONLY | O_WRONLY | O_RDWR) #endif #if !defined (_NODOSDRIVE) && defined (CODEEUC) extern int noconv; #endif #ifdef _NODOSDRIVE # if defined (DNAMESIZE) && DNAMESIZE < (MAXNAMLEN + 1) typedef struct _st_dirent { char buf[(int)sizeof(struct dirent) - DNAMESIZE + MAXNAMLEN + 1]; } st_dirent; # else typedef struct dirent st_dirent; # endif #endif /* _NODOSDRIVE */ #if !defined (_NOKANJIFCONV) || !defined (_NOROCKRIDGE) typedef struct _opendirpath_t { DIR *dirp; char *path; } opendirpath_t; #endif #ifdef CYGWIN #include static struct dirent *NEAR pseudoreaddir __P_((DIR *)); #else #define pseudoreaddir readdir #endif #ifndef _NODOSDRIVE int dosdrive = 0; #endif static char cachecwd[MAXPATHLEN] = ""; #ifndef _NODOSDRIVE static int lastdrv = -1; #endif #if !defined (_NOKANJIFCONV) || !defined (_NOROCKRIDGE) static opendirpath_t *dirpathlist = NULL; static int maxdirpath = 0; #endif #ifndef _NODOSDRIVE int _dospath(path) CONST char *path; { if (!dosdrive) return(0); return((isalpha2(*path) && path[1] == ':') ? *path : 0); } int dospath(path, buf) CONST char *path; char *buf; { CONST char *cp; char *s, tmp[MAXPATHLEN]; int drive, len; if (!dosdrive) return(0); if (_dospath(path)) cp = path; else if (*path == _SC_ || !_dospath(cachecwd)) return(0); else cp = cachecwd; drive = *cp; if (!buf) return(drive); len = sizeof(tmp) - 1; if (cp == buf) { strncpy2(tmp, cp, len); cp = tmp; } # ifdef CODEEUC if (!noconv || cp != path) buf[ujis2sjis(buf, (u_char *)cp, len)] = '\0'; else # endif strncpy2(buf, cp, len); if (cp != path && *path) { s = strcatdelim(buf); len -= s - buf; # ifdef CODEEUC if (!noconv) s[ujis2sjis(s, (u_char *)path, len)] = '\0'; else # endif strncpy2(s, path, len); } return(drive); } #endif /* !_NODOSDRIVE */ DIR *Xopendir(path) CONST char *path; { #if !defined (_NOKANJIFCONV) || !defined (_NOROCKRIDGE) || defined (CYGWIN) char buf[MAXPATHLEN]; #endif DIR *dirp; CONST char *cp; char conv[MAXPATHLEN]; cp = convput(conv, path, 1, 1, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(cp)) dirp = dosopendir(cp); else #endif dirp = opendir(cp); if (!dirp) return(NULL); #if !defined (_NOKANJIFCONV) || !defined (_NOROCKRIDGE) || defined (CYGWIN) realpath2(path, buf, 1); #endif #if !defined (_NOKANJIFCONV) || !defined (_NOROCKRIDGE) dirpathlist = (opendirpath_t *)realloc2(dirpathlist, ++maxdirpath * sizeof(opendirpath_t)); cp = convput(conv, buf, 0, 1, NULL, NULL); dirpathlist[maxdirpath - 1].dirp = dirp; dirpathlist[maxdirpath - 1].path = strdup2(cp); #endif #ifdef CYGWIN #define opendir_saw_u_cygdrive (1 << (8 * sizeof(dirp -> __flags) - 2)) #define opendir_saw_s_cygdrive (1 << (8 * sizeof(dirp -> __flags) - 3)) if (buf[0] != _SC_ || buf[1]) dirp -> __flags |= opendir_saw_u_cygdrive | opendir_saw_s_cygdrive; #endif return(dirp); } int Xclosedir(dirp) DIR *dirp; { #if !defined (_NOKANJIFCONV) || !defined (_NOROCKRIDGE) if (dirp) { int i; for (i = maxdirpath - 1; i >= 0; i--) if (dirp == dirpathlist[i].dirp) break; if (i >= 0) { free(dirpathlist[i++].path); memmove((char *)(&(dirpathlist[i - 1])), (char *)(&(dirpathlist[i])), (maxdirpath-- - i) * sizeof(opendirpath_t)); if (maxdirpath <= 0) { free(dirpathlist); dirpathlist = NULL; } } } #endif /* !_NOKANJICONV || !_NOROCKRIDGE */ #ifndef _NODOSDRIVE if (((dosDIR *)dirp) -> dd_id == DID_IFDOSDRIVE) return(dosclosedir(dirp)); #endif closedir(dirp); return(0); } #ifdef CYGWIN static struct dirent *NEAR pseudoreaddir(dirp) DIR *dirp; { static char *upath = NULL; static char *spath = NULL; struct dirent *dp; if (!upath) { char ubuf[MAXPATHLEN], sbuf[MAXPATHLEN]; cygwin_internal(CW_GET_CYGDRIVE_PREFIXES, ubuf, sbuf); for (upath = ubuf; *upath == _SC_; upath++); # ifdef DEBUG _mtrace_file = "pseudoreaddir(upath)"; # endif upath = strdup2(upath); for (spath = sbuf; *spath == _SC_; spath++); if (*upath && !strpathcmp(spath, upath)) *spath = '\0'; # ifdef DEBUG _mtrace_file = "pseudoreaddir(spath)"; # endif spath = strdup2(spath); } dp = readdir(dirp); if (dirp -> __d_cookie != __DIRENT_COOKIE) return(dp); if (!(*upath)) dirp -> __flags |= opendir_saw_u_cygdrive; if (!(*spath)) dirp -> __flags |= opendir_saw_s_cygdrive; if (dp) { if (*upath && !(dirp -> __flags & opendir_saw_u_cygdrive) && !strpathcmp(dp -> d_name, upath)) dirp -> __flags |= opendir_saw_u_cygdrive; else if (*spath && !(dirp -> __flags & opendir_saw_s_cygdrive) && !strpathcmp(dp -> d_name, spath)) dirp -> __flags |= opendir_saw_s_cygdrive; } else { if (!(dirp -> __flags & opendir_saw_u_cygdrive)) { dp = dirp -> __d_dirent; strcpy(dp -> d_name, upath); dirp -> __flags |= opendir_saw_u_cygdrive; dirp -> __d_position++; } else if (!(dirp -> __flags & opendir_saw_s_cygdrive)) { dp = dirp -> __d_dirent; strcpy(dp -> d_name, spath); dirp -> __flags |= opendir_saw_s_cygdrive; dirp -> __d_position++; } } return(dp); } #endif /* CYGWIN */ struct dirent *Xreaddir(dirp) DIR *dirp; { #if defined (_NODOSDRIVE) && defined (_NOKANJIFCONV) \ && defined (_NOROCKRIDGE) return(pseudoreaddir(dirp)); #else /* !_NODOSDRIVE || !_NOKANJIFCONV || !_NOROCKRIDGE */ # if !defined (_NOKANJIFCONV) || !defined (_NOROCKRIDGE) char path[MAXPATHLEN], conv[MAXPATHLEN]; int i; # endif static st_dirent buf; struct dirent *dp; char *src, *dest; int dos; # ifndef _NODOSDRIVE if (((dosDIR *)dirp) -> dd_id == DID_IFDOSDRIVE) { dp = (struct dirent *)dosreaddir(dirp); dos = 1; } else # endif { dp = pseudoreaddir(dirp); dos = 0; } if (!dp) return(NULL); dest = ((struct dirent *)&buf) -> d_name; # ifdef CYGWIN /* Some versions of Cygwin have neither d_fileno nor d_ino */ if (dos) { src = ((struct dosdirent *)dp) -> d_name; wrap_reclen(&buf) = ((struct dosdirent *)dp) -> d_reclen; } else # endif { src = dp -> d_name; memcpy((char *)(&buf), (char *)dp, dest - (char *)&buf); } if (isdotdir(src)) { strcpy(dest, src); return((struct dirent *)&buf); } # if !defined (_NOKANJIFCONV) || !defined (_NOROCKRIDGE) for (i = maxdirpath - 1; i >= 0; i--) if (dirp == dirpathlist[i].dirp) break; if (i >= 0) { strcatdelim2(path, dirpathlist[i].path, src); if (convget(conv, path, dos) == conv) { if ((src = strrdelim(conv, 0))) src++; else src = conv; } strcpy(dest, src); } else # endif /* !_NOKANJIFCONV || !_NOROCKRIDGE */ # if !defined (_NODOSDRIVE) && defined (CODEEUC) if (dos && !noconv) dest[sjis2ujis(dest, (u_char *)src, MAXNAMLEN)] = '\0'; else # endif strcpy(dest, src); return((struct dirent *)&buf); #endif /* !_NODOSDRIVE || !_NOKANJICONV || !_NOROCKRIDGE */ } VOID Xrewinddir(dirp) DIR *dirp; { #ifndef _NODOSDRIVE if (((dosDIR *)dirp) -> dd_id == DID_IFDOSDRIVE) dosrewinddir(dirp); #endif rewinddir(dirp); } int Xchdir(path) CONST char *path; { #ifndef _NODOSDRIVE int dd; #endif char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); #ifdef _NODOSDRIVE n = (chdir(path)) ? -1 : 0; #else /* !_NODOSDRIVE */ if (preparedrv(_dospath(path), &dd) < 0) n = -1; else if (dd < 0) n = (chdir(path)) ? -1 : 0; else if ((n = doschdir(path)) < 0) shutdrv(dd); else n = (chdir(rootpath)) ? -1 : 0; if (n >= 0) { shutdrv(lastdrv); lastdrv = dd; } #endif /* !_NODOSDRIVE */ LOG1(_LOG_INFO_, n, "chdir(\"%k\");", path); if (n >= 0 && !Xgetwd(cachecwd)) { *cachecwd = '\0'; n = -1; } return(n); } char *Xgetwd(path) char *path; { char *cp, conv[MAXPATHLEN]; if (path == cachecwd || !*cachecwd) /*EMPTY*/; #ifndef _NODOSDRIVE else if (dosdrive && _dospath(cachecwd)) /*EMPTY*/; #endif else { strcpy(path, cachecwd); return(path); } #ifndef _NODOSDRIVE if (dosdrive && lastdrv >= 0) { if (!(cp = dosgetcwd(path, MAXPATHLEN))) return(NULL); if (isupper2(cp[0])) { int i; for (i = 2; cp[i]; i++) { if (issjis1((u_char)(cp[i]))) i++; else cp[i] = tolower2(cp[i]); } } cp = convget(conv, cp, 1); } else #endif /* !_NODOSDRIVE */ { #ifdef USEGETWD cp = (char *)getwd(path); #else cp = (char *)getcwd(path, MAXPATHLEN); #endif if (!cp) return(NULL); cp = convget(conv, cp, 0); } if (cp == path) return(cp); strcpy(path, cp); return(path); } int Xstat(path, stp) CONST char *path; struct stat *stp; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(path)) n = dosstat(path, stp); else #endif n = (stat(path, stp)) ? -1 : 0; return(n); } int Xlstat(path, stp) CONST char *path; struct stat *stp; { #ifndef _NOROCKRIDGE char rpath[MAXPATHLEN]; #endif char conv[MAXPATHLEN]; int n; #ifdef _NOROCKRIDGE path = convput(conv, path, 1, 0, NULL, NULL); #else path = convput(conv, path, 1, 0, rpath, NULL); #endif #ifndef _NODOSDRIVE if (_dospath(path)) n = doslstat(path, stp); else #endif n = (lstat(path, stp)) ? -1 : 0; #ifndef _NOROCKRIDGE if (n >= 0 && *rpath) rrlstat(rpath, stp); #endif return(n); } int Xaccess(path, mode) CONST char *path; int mode; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(path)) n = dosaccess(path, mode); else #endif n = (access(path, mode)) ? -1 : 0; return(n); } int Xsymlink(name1, name2) CONST char *name1, *name2; { char conv1[MAXPATHLEN], conv2[MAXPATHLEN]; int n; name1 = convput(conv1, name1, 1, 0, NULL, NULL); name2 = convput(conv2, name2, 1, 0, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(name1) || _dospath(name2)) n = dossymlink(name1, name2); else #endif n = (symlink(name1, name2)) ? -1 : 0; LOG2(_LOG_WARNING_, n, "symlink(\"%k\", \"%k\");", name1, name2); return(n); } int Xreadlink(path, buf, bufsiz) CONST char *path; char *buf; int bufsiz; { char conv[MAXPATHLEN], lbuf[MAXPATHLEN + 1]; int n, c; path = convput(conv, path, 1, 0, lbuf, &c); #ifndef _NOROCKRIDGE if (*lbuf && (n = rrreadlink(lbuf, lbuf, sizeof(lbuf) - 1)) >= 0) /*EMPTY*/; else #endif #ifndef _NODOSDRIVE if (_dospath(path)) n = dosreadlink(path, buf, bufsiz); else #endif n = readlink(path, lbuf, MAXPATHLEN); if (n >= 0) { lbuf[n] = '\0'; #ifndef _NOKANJIFCONV path = kanjiconv2(conv, lbuf, strsize(conv), c, DEFCODE, L_FNAME); #else path = lbuf; #endif for (n = 0; n < bufsiz && path[n]; n++) buf[n] = path[n]; } return(n); } int Xchmod(path, mode) CONST char *path; int mode; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(path)) n = doschmod(path, mode); else #endif n = (chmod(path, mode)) ? -1 : 0; LOG2(_LOG_NOTICE_, n, "chmod(\"%k\", %05o);", path, mode); return(n); } #ifdef USEUTIME int Xutime(path, times) CONST char *path; CONST struct utimbuf *times; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); # ifndef _NODOSDRIVE if (_dospath(path)) n = dosutime(path, times); else # endif n = (utime(path, times)) ? -1 : 0; LOG1(_LOG_NOTICE_, n, "utime(\"%k\");", path); return(n); } #else /* !USEUTIME */ int Xutimes(path, tvp) CONST char *path; CONST struct timeval *tvp; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); # ifndef _NODOSDRIVE if (_dospath(path)) n = dosutimes(path, tvp); else # endif n = (utimes(path, tvp)) ? -1 : 0; LOG1(_LOG_NOTICE_, n, "utimes(\"%k\");", path); return(n); } #endif /* !USEUTIME */ #ifdef HAVEFLAGS int Xchflags(path, flags) CONST char *path; u_long flags; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); # ifndef _NODOSDRIVE if (_dospath(path)) { errno = EACCES; n = -1; } else # endif n = (chflags(path, flags)) ? -1 : 0; LOG2(_LOG_WARNING_, n, "chflags(\"%k\", %05o);", path, flags); return(n); } #endif /* !HAVEFLAGS */ #ifndef NOUID int Xchown(path, uid, gid) CONST char *path; uid_t uid; gid_t gid; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); # ifndef _NODOSDRIVE if (_dospath(path)) { errno = EACCES; n = -1; } else # endif n = (chown(path, uid, gid)) ? -1 : 0; LOG3(_LOG_WARNING_, n, "chown(\"%k\", %d, %d);", path, uid, gid); return(n); } #endif /* !NOUID */ int Xunlink(path) CONST char *path; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(path)) n = dosunlink(path); else #endif n = (unlink(path)) ? -1 : 0; LOG1(_LOG_WARNING_, n, "unlink(\"%k\");", path); return(n); } int Xrename(from, to) CONST char *from, *to; { char conv1[MAXPATHLEN], conv2[MAXPATHLEN]; int n; from = convput(conv1, from, 1, 0, NULL, NULL); to = convput(conv2, to, 1, 0, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(from)) { if (_dospath(to)) n = dosrename(from, to); else { errno = EXDEV; n = -1; } } else if (_dospath(to)) { errno = EXDEV; n = -1; } else #endif n = (rename(from, to)) ? -1 : 0; LOG2(_LOG_WARNING_, n, "rename(\"%k\", \"%k\");", from, to); return(n); } int Xopen(path, flags, mode) CONST char *path; int flags, mode; { char conv[MAXPATHLEN]; int fd; path = convput(conv, path, 1, 1, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(path)) fd = dosopen(path, flags, mode); else #endif fd = open(path, flags, mode); #ifndef _NOLOGGING switch (flags & O_ACCMODE) { case O_WRONLY: LOG2(_LOG_WARNING_, fd, "open(\"%k\", O_WRONLY, %05o);", path, mode); break; case O_RDWR: LOG2(_LOG_WARNING_, fd, "open(\"%k\", O_RDWR, %05o);", path, mode); break; default: LOG2(_LOG_INFO_, fd, "open(\"%k\", O_RDONLY, %05o);", path, mode); break; } #endif /* !_NOLOGGING */ return(fd); } #ifndef _NODOSDRIVE int Xclose(fd) int fd; { int n; if (fd >= DOSFDOFFSET) n = dosclose(fd); else n = (close(fd)) ? -1 : 0; return(n); } int Xread(fd, buf, nbytes) int fd; char *buf; int nbytes; { int n; if (fd >= DOSFDOFFSET) n = dosread(fd, buf, nbytes); else n = read(fd, buf, nbytes); return(n); } int Xwrite(fd, buf, nbytes) int fd; CONST char *buf; int nbytes; { int n; if (fd >= DOSFDOFFSET) n = doswrite(fd, buf, nbytes); else n = write(fd, buf, nbytes); return(n); } off_t Xlseek(fd, offset, whence) int fd; off_t offset; int whence; { off_t ofs; if (fd >= DOSFDOFFSET) ofs = doslseek(fd, offset, whence); else ofs = lseek(fd, offset, whence); return(ofs); } int Xftruncate(fd, len) int fd; off_t len; { int n; if (fd >= DOSFDOFFSET) n = dosftruncate(fd, len); else n = ftruncate(fd, len); return(n); } int Xdup(oldd) int oldd; { int fd; if (oldd >= DOSFDOFFSET) { errno = EBADF; fd = -1; } else fd = safe_dup(oldd); return(fd); } int Xdup2(oldd, newd) int oldd, newd; { int fd; if (oldd == newd) fd = newd; else if (oldd >= DOSFDOFFSET || newd >= DOSFDOFFSET) { errno = EBADF; fd = -1; } else fd = safe_dup2(oldd, newd); return(fd); } #endif /* !_NODOSDRIVE */ int Xmkdir(path, mode) CONST char *path; int mode; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(path)) n = dosmkdir(path, mode); else #endif n = (mkdir(path, mode)) ? -1 : 0; LOG2(_LOG_WARNING_, n, "mkdir(\"%k\", %05o);", path, mode); return(n); } int Xrmdir(path) CONST char *path; { char conv[MAXPATHLEN]; int n; path = convput(conv, path, 1, 1, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(path)) n = dosrmdir(path); else #endif n = (rmdir(path)) ? -1 : 0; LOG1(_LOG_WARNING_, n, "rmdir(\"%k\");", path); return(n); } FILE *Xfopen(path, type) CONST char *path, *type; { FILE *fp; char conv[MAXPATHLEN]; path = convput(conv, path, 1, 1, NULL, NULL); #ifndef _NODOSDRIVE if (_dospath(path)) fp = dosfopen(path, type); else #endif fp = fopen(path, type); LOG2((*type == 'r') ? _LOG_INFO_ : _LOG_WARNING_, (fp) ? 0 : -1, "fopen(\"%k\", \"%s\");", path, type); return(fp); } #ifndef _NODOSDRIVE FILE *Xfdopen(fd, type) int fd; CONST char *type; { FILE *fp; if (fd >= DOSFDOFFSET) fp = dosfdopen(fd, type); else fp = fdopen(fd, type); return(fp); } int Xfclose(stream) FILE *stream; { int n; if (dosfileno(stream) >= 0) n = dosfclose(stream); else n = fclose(stream); return(n); } int Xfileno(stream) FILE *stream; { int fd; if ((fd = dosfileno(stream)) >= 0) fd += DOSFDOFFSET; else fd = fileno(stream); return(fd); } int Xfeof(stream) FILE *stream; { int n; if (dosfileno(stream) >= 0) n = dosfeof(stream); else n = feof(stream); return(n); } int Xfread(buf, size, nitems, stream) char *buf; int size, nitems; FILE *stream; { int n; if (dosfileno(stream) >= 0) n = dosfread(buf, size, nitems, stream); else n = fread(buf, size, nitems, stream); return(n); } int Xfwrite(buf, size, nitems, stream) CONST char *buf; int size, nitems; FILE *stream; { int n; if (dosfileno(stream) >= 0) n = dosfwrite(buf, size, nitems, stream); else n = fwrite(buf, size, nitems, stream); return(n); } int Xfflush(stream) FILE *stream; { int n; if (dosfileno(stream) >= 0) n = dosfflush(stream); else n = fflush(stream); return(n); } int Xfgetc(stream) FILE *stream; { int c; if (dosfileno(stream) >= 0) c = dosfgetc(stream); else c = fgetc(stream); return(c); } int Xfputc(c, stream) int c; FILE *stream; { int n; if (dosfileno(stream) >= 0) n = dosfputc(c, stream); else n = fputc(c, stream); return(n); } char *Xfgets(s, n, stream) char *s; int n; FILE *stream; { char *cp; if (dosfileno(stream) >= 0) cp = dosfgets(s, n, stream); else cp = fgets(s, n, stream); return(cp); } int Xfputs(s, stream) CONST char *s; FILE *stream; { int n; if (dosfileno(stream) >= 0) n = dosfputs(s, stream); else n = fputs(s, stream); return(n); } #endif /* !_NODOSDRIVE */