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