Cover V05, I02
Article
Listing 1
Sidebar 1

feb96.tar


Listing 1: dosnames.c

======================================================================

* Dosnames: Converts Unix filenames to MSDOS compatible
*
*  Authors:
*
*   Fred Brunet
*
*   Ed Schaefer
*
*=======================================================================


#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>

#define LISTNAME "dosnames.lst"
#define PACKHEADER "This file is used by dosnames to restore packed
file names. Do not erase!\n"

void cant_do(char *filename);
int checkfile(char *filename);
int packname(FILE *fp, char *filename);
int stripchar(char *instr, char c);
void splitstr(char *instring, char divide, char *prefix, char *suffix);
int unpacknames(FILE *fp);
void usage(char *progname);

main (int argc, char *argv[])
{
char filename[FILENAME_MAX];
FILE *fp;
int i, rc;
int packcount = 0;

/* If list file exists, process it */
if ((access(LISTNAME, F_OK) == 0))
{
if ((fp = fopen(LISTNAME, "r")) == NULL)
return positive+2;
rc = unpacknames(fp);
fclose(fp);
if (rc == 0)
remove(LISTNAME);
} else
{
if (argc < 2)
{
usage(argv[0]);
return 1;
}
if ((fp = fopen(LISTNAME, "w")) == NULL)
return +2;

printf("%d file%c to process:\n", argc-1, (argc==2) ? ' ' :   's');

/* Process all the files in the argument list. */
for (i=1; i < argc; i++)
{
strcpy(filename, argv[i]);
rc = checkfile(filename);
switch (rc)
{
case 0:
printf(" %s ok\n", filename);
break;
case 1:     /* uppercase chars, renamed */
packname(fp, filename);
packcount++;
break;
case -1:
fprintf(stderr,
" %s: Cannot convert filenames with paths\n",   filename);
break;
case -2:
fprintf(stderr, " Skipping directory %s\n", filename);
break;
case -3:
fprintf(stderr,
" Cannot process filename %s: contains unprintable characters\n",   filename);
break;
case -4:
fprintf(stderr, " Skipping hidden file %s\n",   filename);
break;
default:
cant_do(filename);
break;
}
}
fclose(fp);
printf("Done.  %d file%c renamed.\n", packcount,
(packcount==1)   ? ' ' : 's');
if (packcount == 0)
remove(LISTNAME);   /* don't leave an empty list */
}
return 0
}

/*===============================================================
* Restore packed names from list.
*/
int unpacknames(FILE *fp)
{
int rc;
char shortname[FILENAME_MAX], longname[FILENAME_MAX];
char command[100];

while((rc = fscanf(fp, "%s %s", shortname, longname)) > 0)
{
printf(" Changing %s back to %s\n", shortname, longname);
sprintf(command, "mv '%s' '%s'", shortname, longname);
system(command);
}

return 0;
}

/*====================================================================*
* 1) Store the current file name in the list file.
* 2) Rename the file to a shorter file name.  The shorter file name
*    just contains the first 8 characters, followed by up to 3   characters.
*    The filename will be MsDos compatible (only one '.', etc)
*/
int packname(FILE *fp, char *filename)
{
char command[200];
char longname[FILENAME_MAX], tempname[FILENAME_MAX],
prefix[FILENAME_MAX], extension[FILENAME_MAX];
char *fptr;
int namefix = 0;

/* Preserve original name */
strcpy(longname, filename);

/* Set filename to lowercase */
fptr = filename;
while (*fptr)
*(fptr++) = tolower(*fptr);

/* Get parts of filename */
splitstr(filename, '.', prefix, extension);

/* take out all periods */
stripchar(prefix, '.');
stripchar(extension, '.');

/* truncate at 8 and 3*/
prefix[8] = 0x00;
extension[3] = 0x00;

/* prepare tempname in case filename is not unique */
strcpy(tempname, prefix);
tempname[6] = 0x00;

/* append 3 character suffix */
if (*extension)
{
sprintf(filename, "%s.%s", prefix, extension);
} else
strcpy(filename, prefix);

/* If the name already exists, make up a new one */
for (namefix=0; (access(filename, F_OK) == 0) && namefix <= 99;   namefix++)
sprintf(filename, "%s%02d.%s", tempname, namefix, extension);

/* Check again.  If there is still not a unique name after 100 tries,
give up.*/
if (access(filename, F_OK) == 0)
{
fprintf(stderr, "***Cannot pack %s into %s- name already   exists\n",
longname, filename);
} else
{
fprintf(fp, "%s %s\n", filename, longname);
printf(" Renaming %s to %s\n", longname, filename);
sprintf(command, "mv %s %s", longname, filename);
system(command);
}

return 0;
}

/*===================================================================
* check if the file should be packed
* return codes: 0 - don't pack (file name short enough and MsDos   legal)
*               1 - pack
*              -1 - bad file name, example: contains full path.
*              -2 - File is a directory.
*              -3 - Other error.
*              -4 - hidden
*/
int checkfile(char *filename)
{
char prefix[FILENAME_MAX], suffix[FILENAME_MAX];
char *fptr;
struct stat stbuf;
int rc;
long isdir;

/* 1) check for complex path.  Skip any filenames with '/' */
if (strchr(filename, '/') != NULL)
return (-1);

rc = stat(filename, &stbuf);

/* 2) skip any directories */
isdir = stbuf.st_mode & S_IFREG;
if (isdir == 0)
return -2;

/* 3) Check if all characters are printable. Skip funny names. */
fptr = filename;
if (*fptr == '.')  /* skip any hidden file */
return (-4);

while (*fptr)
{
if (!isprint(*fptr))
return (-3);

fptr++;
}

/* 4) Check if all characters are lower case.  */
fptr = filename;
while (*fptr)
{
if (isupper(*fptr))
return (1);
fptr++;
}

/* 5) Check if too many characters in filename */
splitstr(filename, '.', prefix, suffix);
/* if there is a dot in suffix then there is more than 1 dot in
filename */
if (strchr(suffix, '.') != NULL)
return (1);
/* MsDos filenames must be 8.3 or smaller */
if ((strlen(prefix) > 8) || (strlen(suffix) > 3))
return (1);
else
return (0);
}

/*==================================================================
* This function splits a string into two parts at divide.
*    If divide is not contained in the string, then prefix=instring,   and
*    suffix = null.
*/
void splitstr(char *instring, char divide, char *prefix, char *suffix)
{
while ((*instring != divide) && *instring)
*(prefix++) = *(instring++);

*prefix = 0x00;

/*
*instring is null if divide was not contained in the string.  Don't
skip over a null or the strcpy will put garbage into suffix.
*/
if (*instring != 0x00)
instring++;

strcpy(suffix, instring);

}

/*===================================================================
* Prints out an error message with that can't do attitude.
*/
void cant_do(char *filename)
{
printf("Sorry, can't pack file %s\n", filename);
}

/*==============================================================*/
/* stripchar: removes all instances of char from string         */
/*==============================================================*/
int stripchar(char *instr, char c)
{
int i, j;

for (i=j=0; instr[i]; i++)
if (instr[i] != c)
instr[j++] = instr[i];

instr[j] = 0x00;
return(j - 1);  /* same as strlen(instr) */
}

void usage(char *progname)
{
fprintf(stderr, "%s: usage- %s filelist\n", progname, progname);
fprintf(stderr, " Converts Unix file names to MS-DOS legal file   names.\n");
fprintf(stderr,
"As each file is converted,  it is stored in dosnames.lst.  If   dosnames.lst\n");
fprintf(stderr,
"exists, each file in the list is converted back to the   original\n");
fprintf(stderr, "name in the list.\n");

fprintf(stderr, "This sp-uitility has no effect on files with legal MS-DOS names\n");

}

/* End of File */