Mail Archives: djgpp/1993/11/09/17:32:44
>
> If they were uploaded, they would be in pub/msdos/djgpp/pub somewhere.
> Note that the djtarx program in djgpp 1.11 does some conversions
> automatically (*.info-* to *.i*, for example) and has always allowed
> you to specify new names for conflicting files as they're being
> untarred.
>
> The FSF distributes a program called "doschk" (latest version is
> doschk-1.1.tar.gz). This program can be used in a Unix area to
> identify potential conflicts when those sources are moved to DOS, so
> that you can fix the names before tarring them together. If you
> encounter a dos-hostile source distribution, please mention this
> program to the distribution's maintainers and *politely* ask them to
> consider running it on their sources. It also checks for SYSV
> 14-character limit conflicts.
>
> DJ
>
>
/* 8dot3.c ... convert filenames to MS-DOS canonical 8.3 form
* $Author: jax $
* $Log: 8dot3.c,v $
* Revision 1.2 1993/09/30 20:28:09 jax
* Changed default so that it merely echoes proposed MS-DOS
* file names ... added -n option to force renaming of actual files.
* Changed help message accordingly.
*
* Revision 1.5 1993/09/30 20:16:14 jax
* Changed typo in help message.
*
* Revision 1.4 1993/09/30 20:11:55 jax
* changed default to not automatically rename files.
*
* Revision 1.3 1993/09/21 19:15:04 jax
* Added more comments.
*
* Revision 1.2 1993/09/21 07:04:34 jax
* Added options.
*
*/
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#define OPTSTRING "Ulfhins"
#define USAGE \
"Usage: %s [-U|-l] [-fhin] [-s/regexp/regexp/] file ... \n\
\n\tEchoes file name(s) as legal MS-DOS nnnnnnnn.ext to stdout.\n\
\n\t Options:\
\n\t-U convert filename to uppercase\
\n\t-l convert filename to lowercase\
\n\t-f force overwrite of extant destination files, only valid with -n,\
\n\t ignored with -i option.\
\n\t-h gives this help.\
\n\t-i ignores, simply skipping extant identically-named destination files.\
\n\t-n rename the file itself.\
\n\t-s/regexp/regexp/\
\n\t\t*NOT IMPLEMENTED* use substitution masks when subbing illegals.\n"
#define TRUE 1
#define FALSE 0
#define LOWER(c) (('A' <= c) && (c <= 'Z') ? c - 'A' + 'a' : c)
#define UPPER(c) (('a' <= c) && (c <= 'z') ? c - 'a' + 'A' : c)
#define LEGAL(c) ((('A' <= c) && (c <= 'Z')) || (('0' <= c) && (c <= '9'))\
|| (('a' <= c) && (c <= 'z')) || member (c, "_^$~!#%%&-{}()@'`"))
/* See IBM Disk Operating System Version 5.0 User's Manual, p. 72 ff. */
char name[9] ; /* 8+\0 */
char ext[4] ; /* 3+\0 */
char dot[2] ; /* 1+\0 */
char newName[14] ; /* 8+dot+3+\0+1 */
int uppercasing = FALSE; /* Default is neither to upper- nor lower-case name */
int lowercasing = FALSE;
int echoing = TRUE; /* Default is to rename */
int forcing = FALSE; /* Default is not to force overwrite */
int ignoring = FALSE; /* Default is to ask on overwrite */
extern int optind; /* Index to next argv entry used by getopt () */
extern int errno; /* Error returns */
int processOpts (int, char **);
void getname (char *);
void dosname (void);
int redosname (char *);
int main (int argc, char **argv) {
int argIndex;
int temp;
/* No file names? Print usage and quit */
if (argc == 1) {
fprintf (stderr, USAGE, *argv);
return (0);
}
/* Process command line options */
if (temp = processOpts (argc, argv))
return (temp);
/* set our index into argv array to that left by getopt () */
argIndex = optind;
/* Loop processing each file in rest of command line */
while (argv[argIndex]) {
getname (argv[argIndex++]);
dosname ();
if (!echoing) /* "echoing" means "only echoing, not renaming." */
if (redosname (argv[argIndex-1])) {
fprintf (stderr, "Couldn't rename %s, errno == %d",
argv[argIndex-1], errno);
return (errno);
}
}
return (0);
}
/* Process and resolve command line options.
* Return 0 if ok and non-zero if error.
*/
int processOpts (int argc, char **argv) {
int option;
/* loop getting options and processing */
while (-1 != (option = getopt (argc, argv, OPTSTRING))) {
switch (option) {
case 'U':
uppercasing = TRUE;
lowercasing = FALSE;
break;
case 'l':
lowercasing = TRUE;
uppercasing = FALSE;
break;
case 'f':
forcing = TRUE;
break;
case 'h':
fprintf (stderr, USAGE, *argv);
exit (0);
break;
case 'i':
ignoring = TRUE;
break;
case 'n':
echoing = FALSE;
break;
}
}
return (0);
}
/* Output the 8.3 */
void dosname (void) {
printf ("%s",name);
printf ("%s",dot);
printf ("%s\n",ext);
}
/* Rename actual file to 8.3 */
int redosname (char *oldName) {
char s[256];
int fp;
memset (newName,'\0', sizeof (newName));
strcpy (newName,name);
strcat (newName,dot);
strcat (newName,ext);
/* check to see if file to rename actually exists */
if (-1 == (fp = open (oldName,O_RDONLY)))
return -1;
/* it exists, close the file id we opened */
close (fp);
/* Does a file with the new name already exist? */
fp = open (newName,O_RDONLY);
/* If so ... */
if (-1 != fp) {
close (fp); /* Close handle we opened */
if (!ignoring) { /* If we're not skipping extants */
if (forcing) { /* If forcibly overwriting, just do it */
return (rename (oldName, newName));
}
/* But if we are not forcibly overwriting, query user */
else {
fflush (stdin);
fflush (stdout);
fflush (stderr);
fprintf (stderr, "%s exists, overwrite? ", newName);
fflush (stderr);
/* This is too much work, but I haven't figured out
how to do this the right way yet ... suggestions? */
scanf ("%s", s);
fflush (stdin);
fflush (stdout);
fflush (stderr);
if ('Y' == (UPPER (*s))) {
return (rename (oldName, newName));
}
else {
return (0);
}
}
return (0);
}
else
return (0);
}
/* The default, filename didn't already exist, so rename source file */
return (rename (oldName, newName));
}
/* Is "c" a member of "set"? */
int member (char c, char *set) {
int i;
for (i=0; i < strlen (set); i++)
if (c == set[i])
return TRUE;
return FALSE;
}
/* Convert a character to a legal MS-DOS filename char, uppercasing or
* lowercasing if that option set.
*/
char convchar (char c) {
/* the default, possibly overwritten below */
char cc = c;
if (uppercasing)
cc = UPPER (c);
if (lowercasing)
cc = LOWER (c);
if (cc == '+')
return ('x');
if (LEGAL (cc))
return (cc);
else
return ('_');
}
/* Find the index of the '.' dot in the filename, if any.
If two dots, first will be found, second will be an illegal char */
int finddot (char *string) {
int i;
for (i = 0; i < strlen (string); i++) {
if (string[i] == '.')
return (i);
}
return (-1);
}
/* Create the name, dot, ext portions of new filename */
void getname (char *string) {
int i;
int dotpos = finddot (string);
memset (name, '\0', sizeof (name)); /* re-init all these */
memset (dot, '\0', sizeof (dot));
memset (ext, '\0', sizeof (ext));
/* If no dot, or if dot is last char in string */
if ((dotpos < 0) || (dotpos == (strlen (string) - 1)))
for (i = 0; (i < strlen (string)) && (i < 8); i++)
name[i] = convchar (string[i]);
else { /* Otherwise, there's a dot to take into account */
/* For the characters before the dot, up to eight (8) chars max */
for (i = 0; (i < strlen (string)) && (i < dotpos) && (i < 8); i++)
name[i] = convchar (string[i]);
/* For the chars after the dot, up to three (3) max */
for (i = (dotpos+1); (i < strlen (string)) &&
((i - (dotpos + 1)) < 3); i++)
ext[i-(dotpos+1)] = convchar (string[i]);
/* insert dot ... made this a separate step for reasons having
to do with the NUL: device which no longer apply, but not
worth changing now. */
*dot = '.';
}
}
- Raw text -