Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

LFN Capable CLIB

3 views
Skip to first unread message

Blair Campbell

unread,
Jan 26, 2006, 11:56:53 PM1/26/06
to
Is it a possibility that in the future, the OpenWatcom Clib for 16 and
32-bit DOS will have an lfn-capable equivalent, linked in by for example
specifying a certain command-line argument like -link-lfn or something
like that? Something that would allow programs to be recompiled to add
LFN support?

Roald Ribe

unread,
Jan 26, 2006, 11:56:55 PM1/26/06
to

Look at the 9th entry on this page.
http://www.azillionmonkeys.com/qed/watcom.html

I have no idea if/how it works. But if you look at it, please
enlighten others here in the group.

Roald

Roald Ribe

unread,
Jan 26, 2006, 11:56:55 PM1/26/06
to
JimS wrote:
> It hooks int 21 and translates all the calls to del/open/cd etc to use
> LFN int calls. Good chance it'll work.

I guess that on plain DOS one would have to install something like:
http://www.geocities.com/jadoxa/doslfn/index.html

But on other systems, would the int 21 hook work on 95/98/Me and NT
and OS/2, and give acces to long file names on all those systems?

Roald

JimS

unread,
Jan 26, 2006, 11:56:56 PM1/26/06
to
On Thu, 26 Jan 2006 11:17:41 +0100, Roald Ribe
<rr.n...@pogostick.net> wrote:

>JimS wrote:
>> On Thu, 26 Jan 2006 09:53:50 +0100, Roald Ribe
>> <rr.n...@pogostick.net> wrote:
>>
>>
>>>Blair Campbell wrote:
>>>
>>>>Is it a possibility that in the future, the OpenWatcom Clib for 16 and
>>>>32-bit DOS will have an lfn-capable equivalent, linked in by for example
>>>>specifying a certain command-line argument like -link-lfn or something
>>>>like that? Something that would allow programs to be recompiled to add
>>>>LFN support?
>>>
>>>Look at the 9th entry on this page.
>>>http://www.azillionmonkeys.com/qed/watcom.html
>>>
>>>I have no idea if/how it works. But if you look at it, please
>>>enlighten others here in the group.
>>
>>
>> It hooks int 21 and translates all the calls to del/open/cd etc to use
>> LFN int calls. Good chance it'll work.
>
>I guess that on plain DOS one would have to install something like:
>http://www.geocities.com/jadoxa/doslfn/index.html

I doubt that will work. One could try.

>But on other systems, would the int 21 hook work on 95/98/Me and NT
>and OS/2, and give acces to long file names on all those systems?

The check in there checks for Win9x - whether that's good enough to
detect NT or OS2, I don't know, but it would be easy to fix. Does OS2
support Int 21 fn 71? In Win9x's DOS, Int 21 function 71 takes ah as
the old DOS function number and extends the filename - that's all the
ISR patch does.
eg. for mkdir
Int 21 al = 39
ds:dx points at filename
becomes
Int 21 al=71 ah=39
ds:dx points at long filename

This first hack could easily be patched into an application (or even
made a crt function).

JimS

JimS

unread,
Jan 26, 2006, 11:56:55 PM1/26/06
to
On Thu, 26 Jan 2006 09:53:50 +0100, Roald Ribe
<rr.n...@pogostick.net> wrote:

It hooks int 21 and translates all the calls to del/open/cd etc to use


LFN int calls. Good chance it'll work.

JimS

Michal Necasek

unread,
Jan 26, 2006, 11:56:54 PM1/26/06
to
It's a possibility if and only if someone contributes the necessary
work. I am not entirely certain what sort of changes the clib would
require, or what it would take to have both 'traditional' and LFN
support in the same library (without complicating things too much). I
stopped using DOS around the time VFAT came out...

BTW, assuming you're the same Blair Campbell who put up a DOS-only
archive of OW 1.4, I wonder if you're aware of the following:

- The Windows and OW/2 installers are self-extracting ZIP files and I
don't see why they couldn't be unzipped on DOS.

- Since OW 1.4 uses the 'old' Watcom installer, it is possible to
build a DOS version of the installer. Nobody has worked on that but it
should not be terribly difficult for an interested DOS user. It might be
simplest to set up the DOS installer as a small "add-on" that would use
either the Windows or OS/2 installer as source of installable files.
This could be part of the official release.


Michal

Blair Campbell

unread,
Jan 26, 2006, 11:56:55 PM1/26/06
to
Michal Necasek wrote:

> Blair Campbell wrote:
> > Is it a possibility that in the future, the OpenWatcom Clib for 16 and
> > 32-bit DOS will have an lfn-capable equivalent, linked in by for example
> > specifying a certain command-line argument like -link-lfn or something
> > like that? Something that would allow programs to be recompiled to add
> > LFN support?
> >
> It's a possibility if and only if someone contributes the necessary
> work. I am not entirely certain what sort of changes the clib would
> require, or what it would take to have both 'traditional' and LFN
> support in the same library (without complicating things too much). I
> stopped using DOS around the time VFAT came out...

I might be interested in this when I free up some space on my hard drive
for the source code.

> BTW, assuming you're the same Blair Campbell who put up a DOS-only
> archive of OW 1.4, I wonder if you're aware of the following:

Correct

> - The Windows and OW/2 installers are self-extracting ZIP files and I
> don't see why they couldn't be unzipped on DOS.

Lots of FreeDOS users wanted a DOS-only archive because they thought
that the installers available were too large.

> - Since OW 1.4 uses the 'old' Watcom installer, it is possible to
> build a DOS version of the installer. Nobody has worked on that but it
> should not be terribly difficult for an interested DOS user. It might be

Perhaps I'll look into this.

Rod Pemberton

unread,
Jan 26, 2006, 11:56:58 PM1/26/06
to

"JimS" <so...@not.com> wrote in message
news:pmdht1lkk1q32c4qh...@4ax.com...

> On Thu, 26 Jan 2006 11:17:41 +0100, Roald Ribe
> <rr.n...@pogostick.net> wrote:
>
> >JimS wrote:
> >> On Thu, 26 Jan 2006 09:53:50 +0100, Roald Ribe
> >> <rr.n...@pogostick.net> wrote:
> >>
> >>
> >>>Blair Campbell wrote:
> >>>
> >>>>Is it a possibility that in the future, the OpenWatcom Clib for 16 and
> >>>>32-bit DOS will have an lfn-capable equivalent, linked in by for
example
> >>>>specifying a certain command-line argument like -link-lfn or something
> >>>>like that? Something that would allow programs to be recompiled to
add
> >>>>LFN support?
> >>>
> >>>Look at the 9th entry on this page.
> >>>http://www.azillionmonkeys.com/qed/watcom.html
> >>>
> >>>I have no idea if/how it works. But if you look at it, please
> >>>enlighten others here in the group.
> >>
> >>
> >> It hooks int 21 and translates all the calls to del/open/cd etc to use
> >> LFN int calls. Good chance it'll work.

Yeah, that's how it works. The only other LFN software I'm aware of which
promotes interrupts was Chris Jones' LFNDOS. If your working with C, you
can get away with 716C and 7156. I'll append a port of RPMUNPAC.C (I've
posted this before on another newsgroup) which shows how to use DOSLFN with
DJGPP and OW. There is one problem I came across: getting DOSLFN with OW to
flush it's buffers. This was found on the Henrik Haftmann versions before
Jason Hood. So, it might not be a problem anymore...

> >I guess that on plain DOS one would have to install something like:
> >http://www.geocities.com/jadoxa/doslfn/index.html
>
> I doubt that will work. One could try.

I think that it would work. DOSLFN will be loaded first, and that code
calls the old int 21.

> >But on other systems, would the int 21 hook work on 95/98/Me and NT
> >and OS/2, and give acces to long file names on all those systems?

My experience for 98/98SE is that the DOS box interrupts are an almost a
perfect clone of DOS. I've used some very aggressive interrupt tracking and
tracing, using the trap flag, without making any changes for 98/98SE. I've
even run OW and DJGPP PM apps which redo many interrupts without problems.

> The check in there checks for Win9x - whether that's good enough to
> detect NT or OS2, I don't know, but it would be easy to fix. Does OS2
> support Int 21 fn 71? In Win9x's DOS, Int 21 function 71 takes ah as
> the old DOS function number and extends the filename - that's all the
> ISR patch does.
> eg. for mkdir
> Int 21 al = 39
> ds:dx points at filename
> becomes
> Int 21 al=71 ah=39
> ds:dx points at long filename
>
> This first hack could easily be patched into an application (or even
> made a crt function).
>
> JimS

Rod Pemberton

PS, RPMUNPAC.C

/*
* rpmunpack.c - Utility program to unpack an RPM archive
*
* Gero Kuhlmann <ge...@gkminix.han.de> 1998
*
* This program is public domain software; you can do whatever you like
* with this source, including modifying and redistributing it.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
*
*/

/*
* DJGPP LFN code and all WATCOM code
* contributed to the Public Domain by
* Rod Pemberton 2003-2005
*
* DJGPP gcc -o rpmunpac.exe rpmunpac.c
* WATCOM wcl/l=dos rpmunpac.c
* or wcl386/l=dos4g rpmunpac.c
*
* USAGE:
* doslfn
* rpmunpac file.rpm
* gzip -d file.gz
* cpio -iudv < file.cpio
* djtar -xvf file.tar (djtar has lfn support, DJGPP's GNU tar
doesn't)
*
* (doslfn from Henrik Haftmann)
* ( http://www.tu-chemnitz.de/~heha/hs_freeware/doslfn.zip )
* (dos cpio, gzip, djtar from DJ Delorie)
* ( http://www.delorie.com )
*/


#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
#include <dos.h>

#ifdef __DJGPP__
#include <dpmi.h>
#include <go32.h>
#include <crt0.h>
#include <dir.h>
__dpmi_regs r;
char ** __crt0_glob_function(char *arg) { return (char **)0; }
void __crt0_load_environment_file(char *app_name) {}
#define MX_PTH MAXPATH
#endif

#ifdef __WATCOMC__
#include <i86.h>
union REGS r;
struct SREGS s;
struct {
unsigned long EDI,ESI,EBP,rsvd,EBX,EDX,ECX,EAX;
unsigned short flags,ES,DS,FS,GS,IP,CS,SP,SS;
} RMI;
#define MX_PTH _MAX_PATH
/* tb used to setup transfer buffer below 1st megabyte (DJGPP __tb) */
/* DOS can only access the first 1Mb of memory */
/* tb used to save return information from DOS calls */
void *tb;
unsigned short sel; /* sel needed to free allocated memory, don't use */

#endif

/*
* Some general definitions
*/
#define BUFSIZE 512
#define RPM_MAGIC "\xED\xAB\xEE\xDB"
#define GZ_MAGIC_1 '\x1F'
#define GZ_MAGIC_2 '\x8B'
#define OFFS 261

/*
* Global variables
*/
static char buffer[BUFSIZE],short_name[9],long_name[65];
static char *progname;
FILE *infile, *outfile;
unsigned char sfnt[256];

#ifdef __WATCOMC__
/* setup tb - transfer buffer for dos calls in memory below 1Mb */
void free_dos_mem(void)
{
#ifdef __386__
r.w.ax=0x0101; /* free dos memory */
r.w.dx=sel;
int386(0x31,&r,&r);
#else
free (tb);
#endif
}

void get_dos_mem(void)
{
#ifdef __386__
r.w.ax=0x0100; /* allocate dos memory, no __tb in Watcom */
r.w.bx=0x400; /* 04000h (16384 bytes) in paragraphs (16 bytes) */
int386(0x31,&r,&r);
sel = r.w.dx;
tb = (void *)(r.w.ax<<4);
#else
tb = malloc (16384);
if (tb==NULL)
{
printf("RM malloc failed.\n");
exit(1);
}
#endif
}
#endif

void lfn_7156(char *opath, char *npath)
{
#ifdef __DJGPP__
dosmemput(opath, MX_PTH, __tb);
dosmemput(npath, MX_PTH, __tb+OFFS);
r.x.ax = 0x7156;
r.x.ds = __tb>>4;
r.x.dx = 0;
r.x.es = (__tb+OFFS)>>4;
r.x.di = (__tb+OFFS)&0x0F;
r.x.flags |= 1;
__dpmi_int(0x21, &r);
#endif
#ifdef __WATCOMC__
#ifdef __386__
memcpy(tb,opath,MX_PTH);
memcpy((char *)tb+OFFS,npath,MX_PTH);
RMI.EAX = 0x7156;
RMI.DS = (unsigned long)tb>>4;
RMI.EDX = 0;
RMI.ES = ((unsigned long)tb+OFFS)>>4;
RMI.EDI = ((unsigned long)tb+OFFS)&0x0F;
RMI.flags = INTR_CF; /* set carry */
r.w.ax=0x0300; /* simulate real mode interrupt */
r.h.bl=0x21;
r.h.bh=0;
r.w.cx=0;
s.es=FP_SEG(&RMI);
r.x.edi=FP_OFF(&RMI);
int386x(0x31,&r,&r,&s);
#else
movedata(FP_SEG(opath), FP_OFF(opath), FP_SEG(tb), FP_OFF(tb),
MX_PTH);
movedata(FP_SEG(npath), FP_OFF(npath), FP_SEG((char *)tb+OFFS),
FP_OFF((char *)tb+OFFS), MX_PTH);
r.w.ax = 0x7156;
s.ds = FP_SEG(tb);
r.w.dx = FP_OFF(tb);
s.es = FP_SEG((char *)tb+OFFS);
r.w.di = FP_OFF((char *)tb+OFFS);
r.w.cflag = INTR_CF;
int86x(0x21,&r,&r,&s);
#endif
#endif
}

#define COE 0x0011 /* create, open if exists */
#define CFE 0x0010 /* create, fail if exists */
#define CTE 0x0012 /* create, truncate if exists */
#define OFN 0x0001 /* open, fail if does not exist */
#define TFN 0x0002; /* truncate, fail if does not exist */

int lfn_716C(char *mpath, unsigned *fhandle)
{
#ifdef __DJGPP__
dosmemput( mpath, MX_PTH,__tb);
r.x.ax = 0x716c;
r.x.bx = 0x0002;
r.x.cx = 0;
r.x.dx = OFN;
r.x.ds = __tb>>4;
r.x.si = 0;
r.x.di = 0;
r.x.flags |= 1;
__dpmi_int(0x21, &r);
*fhandle = r.x.ax;
return(r.x.flags&0x01);
#endif
#ifdef __WATCOMC__
#ifdef __386__
memcpy(tb,mpath,MX_PTH);
RMI.EAX = 0x716c;
RMI.EBX = 0x0002;
RMI.ECX = 0;
RMI.EDX = OFN;
RMI.DS = (unsigned long)tb>>4;
RMI.ESI = (unsigned long)tb&0x0F;
RMI.EDI = 0;
RMI.flags = INTR_CF; /* set carry */
r.w.ax=0x0300; /* simulate real mode interrupt */
r.h.bl=0x21;
r.h.bh=0;
r.w.cx=0;
s.es=FP_SEG(&RMI);
r.x.edi=FP_OFF(&RMI);
int386x(0x31,&r,&r,&s);
*fhandle = RMI.EAX;
return(RMI.flags&INTR_CF);
#else
movedata(FP_SEG(mpath), FP_OFF(mpath), FP_SEG(tb), FP_OFF(tb),
MX_PTH);
r.w.ax = 0x716c;
r.w.bx = 0x0002;
r.w.cx = 0;
r.w.dx = OFN;
s.ds = FP_SEG(tb);
r.w.si = FP_OFF(tb);
r.w.di = 0;
r.w.cflag = INTR_CF;
int86x(0x21,&r,&r,&s);
*fhandle = r.w.ax;
return(r.w.cflag);
#endif
#endif
}

void lfn_3E(unsigned fhandle)
{
#ifdef __DJGPP__
r.h.ah = 0x3E;
r.x.bx = fhandle;
r.x.flags |= 1;
__dpmi_int(0x21, &r);
#endif
#ifdef __WATCOMC__
#ifdef __386__
RMI.EAX = 0x3E00;
RMI.EBX = fhandle;
RMI.flags = INTR_CF;
r.w.ax=0x0300; /* simulate real mode interrupt */
r.h.bl=0x21;
r.h.bh=0;
r.w.cx=0;
s.es=FP_SEG(&RMI);
r.x.edi=FP_OFF(&RMI);
int386x(0x31,&r,&r,&s);
#else
r.h.ah = 0x3E;
r.w.bx = fhandle;
r.w.cflag = INTR_CF;
int86(0x21,&r,&r);
#endif
#endif
}

/*
* Read a specified number of bytes from input file
*/
static void myread(int num)
{
int err;

if ((err = fread(( char *) &buffer, sizeof( char), num, infile)) != num) {
if (err < 0)
perror(progname);
else
fprintf(stderr, "unexpected end of input file\n");
exit(1);
}
}


/*
* Main program
*/
int main(int argc, char **argv)
{
int len, status = 0;
unsigned int i;

#ifdef __WATCOMC__
unsigned int fh=0;
atexit(free_dos_mem);
get_dos_mem();
#endif

/* Get our own program name */
if ((progname = strrchr(argv[0], '/')) == NULL)
progname = argv[0];
else
progname++;

/* Check for command line parameters */
if (argc != 2) {
fprintf(stderr, "usage: %s [RPM file]\n", argv[0]);
exit(1);
}

/* Open input file */
if ((infile = fopen(argv[1],"rb"))==NULL) {
perror(progname);
exit(1);
}

/* Read magic ID and output filename */
myread(4);
if (strncmp(buffer, RPM_MAGIC, 4)) {
fprintf(stderr, "input file is not in RPM format\n");
exit(1);
}
myread(6); /* Skip flags */
myread(64);
buffer[64] = '\0';

/* MS-DOS filename 8.3 A-Z a-z 0-9 _^$~!#%&-{}@`\'() */
for (i=0;i<256;i++) { /* setup SFN translation table */
sfnt[i]=i;
if (!isalnum(i) && strchr("_^$~!#%&-{}@`\'()\0",i)==NULL)
sfnt[i]='_';
}
short_name[4] = '\0';
strcpy(long_name,buffer);
for (i=0;i<4;i++) {
short_name[i] = sfnt[(int)buffer[i]];
}
strcat(short_name, ".gz");

/* Open output file */
strcat(long_name, ".cpio.gz");
printf ("%s\n%s\n",short_name,long_name);
if ((outfile = fopen(short_name,"wb"))==NULL) {
perror(progname);
exit(1);
}

/*
* Now search for the GZIP signature. This is rather awkward, but I don't
* know any other way how to find out the exact starting position of the
* archive within the input file. There are a couple of data structures
* and texts (obviously descriptions, installation shell scripts etc.)
* coming before the archive, but even they start at different offsets
* with different RPM files. However, it looks like the GZIP signature
* never appears before offset 0x200, so we skip these first couple of
* bytes to make the signature scan a little more reliable.
*/
myread(0x200 - 74);
while (status < 2) {
myread(1);
if ((status == 0) && (buffer[0] == GZ_MAGIC_1))
status++;
else if ((status == 1) && (buffer[0] == GZ_MAGIC_2))
status++;
else
status = 0;
}
buffer[0] = GZ_MAGIC_1;
buffer[1] = GZ_MAGIC_2;
if (fwrite(( char *) &buffer, sizeof( char), 2, outfile) < 0) {
perror(progname);
exit(1);
}

/* Now simply copy the GZIP archive into the output file */
while ((len = fread(( char *) &buffer, sizeof( char), BUFSIZE, infile)) >
0) {
if (fwrite(( char *) &buffer, sizeof( char), len, outfile) < 0) {
perror(progname);
exit(1);
}
}
if (len < 0) {
perror(progname);
exit(1);
}

fclose(infile);
fclose(outfile);

#ifdef __WATCOMC__
if (lfn_716C(short_name, &fh)==0) /* force LFN driver cache update */
lfn_3E(fh); /* close file, if it opened */
#endif
lfn_7156(short_name, long_name); /* LFN rename */

return(0);
}

Blair Campbell

unread,
Jan 31, 2006, 12:04:38 AM1/31/06
to
Roald Ribe wrote:

For some functions this method would work well, but for some interrupts
there are incompatibilities like with findfirst/findnext: the find_t
block would need to be modified to allow filenames longer than 8+3 and
also the form is different. In any case, the same function should be
able to work but with complete LFN capability. For example, an
LFN-capable findfirst would call the interrupt, edit the find_t block to
contain equivalent values, and then other functions that conventionally
use short names would be extended to use long names, so that a program
could simply be recompiled to gain LFN support. Just a thought.

0 new messages