Date: Sun, 7 Sep 1997 13:01:51 +0300 (IDT) From: Eli Zaretskii To: DJ Delorie cc: djgpp-workers AT delorie DOT com Subject: Re: djgpp 2.02 alpha 970831 In-Reply-To: <199708312149.RAA26964@delorie.com> Message-ID: MIME-Version: 1.0 Content-Type: TEXT/PLAIN; charset=US-ASCII Precedence: bulk On Sun, 31 Aug 1997, DJ Delorie wrote: > I still have a fork() implementation from > that nobody has commented on. I don't think I saw this. Could you mail it to me? Thanks. > There were some conflicting _use_lfn.c patches. The ones that didn't > make it were the getenv() optimizations, since they seemed less agreed > upon. Here's the version I use for the past few months. Robert, can you compare this with yours? They should be identical, I think. /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */ /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include static int use_lfn_bss_count = -1; /* if we are restarted (emacs) */ static unsigned filesystem_flags = _FILESYS_UNKNOWN; static char _lfnenv = 'y'; /* remember here the value of $LFN */ static unsigned last_env_changed = 0; static int last_drive; /* drive *letter*, not *number*! */ /* Return the parameters of the filesystem where PATH resides. */ unsigned _get_volume_info (const char *path, int *maxfile, int *maxpath, char *fsystype) { __dpmi_regs r; unsigned long tbuf_la = __tb & 0xfffff; unsigned long tbuf_seg = tbuf_la >> 4; unsigned retval; if (path && *path) { if (path[1] == ':') { dosmemput (path, 3, tbuf_la); tbuf_la += 3; if (path[2] != '\\') _farpokeb(_dos_ds, tbuf_la - 1, '\\'); _farpokeb(_dos_ds, tbuf_la++, '\0'); } else if (*path == '\\' && path[1] == '\\') { int plen = strlen (path) + 1; /* FIXME: what should we do with the UNC pathnames like "\\machine\vol\path"? We need to know either their DOS drive letter or where does the root directory path ends. For now, we assume the entire path is the root path. */ dosmemput (path, plen, tbuf_la); tbuf_la += plen + 1; } } /* No explicit drive, use default drive. */ if (tbuf_la == __tb) { unsigned drv_no; /* FIXME: can `_dos_getdrive' fail (e.g. no floppy in drive)? */ _dos_getdrive(&drv_no); _farpokeb(_dos_ds, tbuf_la++, 'A' + drv_no - 1); _farpokeb(_dos_ds, tbuf_la++, ':'); _farpokeb(_dos_ds, tbuf_la++, '\\'); _farpokeb(_dos_ds, tbuf_la++, '\0'); } r.x.ax = 0x71a0; /* Get Volume Information function */ r.x.ds = tbuf_seg; /* DS:DX points to root directory name */ r.x.dx = 0; r.x.es = tbuf_seg; /* ES:DI points to a buffer for filesys name */ r.x.di = (tbuf_la - __tb) & 0xffff; r.x.cx = 32; /* max size of filesystem name (Interrupt List) */ __dpmi_int(0x21, &r); if ((r.x.flags & 1) == 0 && r.x.ax != 0x7100) { char *p = fsystype, c; retval = r.x.bx; if (maxfile) *maxfile = r.x.cx; if (maxpath) *maxpath = r.x.dx; if (fsystype) { /* Only copy as much as required, in case the buffer isn't large enough for 32 bytes. */ _farsetsel (_dos_ds); while ((c = _farnspeekb (tbuf_la++))) *p++ = c; *p = '\0'; } } else { errno = ENOSYS; retval = 0; /* meaning none of the features supported */ if (maxfile) *maxfile = 13; if (maxpath) *maxpath = 80; if (fsystype) *fsystype = '\0'; } return retval; } char _use_lfn (const char *path) { int same_drive_as_last_time; if (_crt0_startup_flags & _CRT0_FLAG_NO_LFN) { /* Don't update the static counters, so the first time after NO_LFN flag is reset, the environment and the filesystem will be queried. */ return 0; } /* Forget everything we knew before we were dumped (Emacs). */ if (use_lfn_bss_count != __bss_count) { use_lfn_bss_count = __bss_count; filesystem_flags = _FILESYS_UNKNOWN; _lfnenv = 'y'; last_drive = 0; } same_drive_as_last_time = 1; if (path) { /* FIXME: a UNC PATH will always force a call to `_get_volume_info'. */ if ((path[1] == ':' && toupper (*path) != last_drive) || (*path == '\\' && path[1] == '\\')) same_drive_as_last_time = 0; else { unsigned drv_no; _dos_getdrive(&drv_no); if (drv_no - 1 + 'A' != last_drive) same_drive_as_last_time = 0; } } if (!same_drive_as_last_time || last_env_changed != __environ_changed || filesystem_flags == _FILESYS_UNKNOWN) { /* Check the environment for $LFN. */ char *lfnenv; last_env_changed = __environ_changed; lfnenv = getenv ("LFN"); if(lfnenv && (tolower (lfnenv[0]) == 'n')) { _lfnenv = 'n'; last_drive = 0; } else { /* If $LFN was not set or isn't 'n', assume 'y'. */ _lfnenv = 'y'; } } if (!same_drive_as_last_time || filesystem_flags == _FILESYS_UNKNOWN) filesystem_flags = _get_volume_info (path, 0, 0, 0); return ((filesystem_flags & _FILESYS_LFN_SUPPORTED) != 0 && _lfnenv != 'n'); } #ifdef TEST int main (int argc, char *argv[]) { char *path = "."; unsigned flags; char fsname[32]; int maxfile, maxpath; printf ("_USE_LFN reports %d at startup\n", _USE_LFN); if (argc > 1) path = argv[1]; flags = _get_volume_info (path, &maxfile, &maxpath, fsname); printf ("Flags: %x, MaxFile: %d, MaxPath: %d, FSName: %s\n", flags, maxfile, maxpath, fsname); _crt0_startup_flags |= _CRT0_FLAG_NO_LFN; printf ("_USE_LFN reports %d when _CRT0_FLAG_NO_LFN is set\n", _USE_LFN); _crt0_startup_flags &= ~_CRT0_FLAG_NO_LFN; putenv ("LFN=y"); printf ("_USE_LFN reports %d when LFN is set to Y\n", _USE_LFN); putenv ("LFN=n"); printf ("_USE_LFN reports %d when LFN is set to N\n", _USE_LFN); return 0; } #endif