delorie.com/archives/browse.cgi   search  
Mail Archives: djgpp/1993/11/09/17:32:44

From: jax AT darkstar DOT cygnus DOT com (Jack Woehr)
Subject: Re: Conversion of Unix to DOS file names
To: dj AT ctron DOT com (DJ Delorie)
Date: Tue, 9 Nov 1993 14:41:18 -0700 (MST)
Cc: jon AT halsp DOT hitachi DOT com, djgpp AT sun DOT soe DOT clarkson DOT edu

> 
> 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 -


  webmaster     delorie software   privacy  
  Copyright © 2019   by DJ Delorie     Updated Jul 2019