[alt.msdos.programmer] Setting attributes of MS-DOS files

leemc@csri.toronto.edu (Matthew Lee) (06/02/90)

I am trying to set bit 6 of the attribute byte of a DOS file.  I want to be 
able to flag a set of files and since bits 0-5 are used for the read-only, 
hidden, ... attributes and bit 7 is used by Novell Netware, bit 6 seems 
the least likely to conflict with other things. However, my attempts to use
the C "_chmod" function and to use DOS interrupt 21, function 43 have been
unsuccessful, I don't think they expect anybody to do this.

Can anybody help me out with this?

Thanks
Matthew Lee
leemc@csri.toronto.edu

pozar@kumr.UUCP (Tim Pozar) (06/05/90)

In article <1990Mar31.125044.18181@jarvis.csri.toronto.edu> leemc@csri.toronto.edu (Matthew Lee) writes:
>I am trying to set bit 6 of the attribute byte of a DOS file.  I want to be 
>able to flag a set of files and since bits 0-5 are used for the read-only, 
>hidden, ... attributes and bit 7 is used by Novell Netware, bit 6 seems 
>the least likely to conflict with other things. However, my attempts to use
>the C "_chmod" function and to use DOS interrupt 21, function 43 have been
>unsuccessful, I don't think they expect anybody to do this.
>
>Can anybody help me out with this?
>
>Thanks
>Matthew Lee
>leemc@csri.toronto.edu

    Check this out.  I wrote this bypassing MicroSoft's chmod and 
dos_findfirst, findnext.

                    Tim
---

/*
    CHMOD 

    For MS-DOS.


    11.July.1988

    This program is Freeware.  You can use it to your hearts content without
    the feeling you are ripping me off.  If you redistribute this source or
    binary, the copyright statement must be included.  Please see the help
    display for more info.

    I ripped off some of the "interface" from the UN*X CHMOD.  I am also 
    waiting for AT&T to sue me for "look-and-feel".  

    I am giving out the source so you can compile it your-self, or as an
    education on how to do certain hacks.

    Some things you may want to check out are how to do file searches without
    going through Microsoft C 5.x's brain damaged _dos_findfirst() and 
    _dos_findnext() functions.  Also you may want to rip off the code to get 
    the time and date out of MS-DOS's packed time and date ints.

                 Tim

    If you want to send me fan mail:

    Tim Pozar
    KKSF
    77 Maiden Lane 
    San Francisco CA 94131
    (415) 788-2022

    FidoNet  1:125/555
    Internet Tim.Pozar@fidogate.fidonet.org
    Usenet   {lll-winken, hoptoad}!fidogate!pozar
*/

/*
    Makefile:
--- cut here ---
chmod.exe:	chmod.c
	cl /Zp chmod.c
--- cut here ---

*/

/*
     History:
1.0 19.Aug.88
    Full release. TMP

1.1 26.Dec.88
    Added volume label routines.  (What else to do after XMAS?) TMP

1.2 8.Jan.89
    Now supports subdirectories. TMP

1.3 25.Jul.89
    Added 'r' switch to be compatible with 'attrib'.
*/

#include <memory.h>
#include <string.h>
#include <stdio.h>
#include <dos.h>

#define TRUE 1
#define FALSE 0

	/* Attribute bits */
#define RO 0x01		/* Read only attribute. */
#define HI 0x02		/* Hidden attribute, */
#define SY 0x04		/* System attribute, */
#define VO 0x08		/* Volume ID */
#define DI 0x10		/* Subdirectory */
#define AR 0x20		/* Archive, */
#define U1 0x40		/* Unused */
#define U2 0x80		/* Unused */

#define SS 80		/* A string length */

/* Structure for find first/next (find()).
NOTE: the DPB pointer is a double word 
character pointer; here it is declared as a
long, to avoid problems with the various
size of char *'s.
*/

struct _xfbuf {

char s_attrib;		/* Search attribute */

/* These do not need to be initialized */

char drive;		/* 0 == current, 1 == A: ... */
char fcbname[11];	/* FCB name, */
unsigned ent;
long dpb_ptr;
unsigned dirstart;

/* These are returned by DOS */
char f_attrib;		/* found attribute, */
unsigned time;		/* Packed time, */
unsigned date;		/* Packed date */
long fsize;		/* file size, */
char name[13];		/* found name */
};

int ver = 1;		/* version number */
int rev = 3;		/* revision number */
char date[] = "25.Jul.89\0";

int flag = FALSE;
int findflag = 0;
int year,month,day,hour,minute,second;

main(argc,argv)
int argc;
char *argv[];
{
char findname[SS];		/* Search name, may contain wild cards */
char filename[SS];		/* Specific file name, no wild cards */
char tempname[SS];		/* An above average buffer for general use */
int att;
int i, x, y;
int result;
struct _xfbuf xfbuf;

i = 0;

printf("CHMOD %d.%d %s Copyright 1988,1989 Tim Pozar      FidoNet 1:125/406\n\n",ver,rev,date);

if (argc <2){
  printf(" Syntax:\n");
  printf("%s [+-][ahrsw] filename\n",argv[0]);
  printf(" Where\n");
  printf("   + = set bit or \"turn-on\"\n");
  printf("   - = reset bit or \"turn-off\"\n");
  printf("   a = Archive - Indicates file has NOT been backed up.\n");
  printf("   h = Hidden  - Hides file from directory listings.\n");
  printf("   r = Read    - Turns on or off Write permission.\n");
  printf("   s = System  - A hold over from CP/M.  Will hide files too.\n");
  printf("   w = Write   - Turns off or on Write permission.\n");
  printf("                 All files have Read permission.\n");
  printf("   Only one bit can be toggled at once, but \"filename\" can \n");
  printf("   contain wildcards for global settings.\n");
  printf("\n");
  printf("   If you only specify the file name, you will get\n");
  printf("   a listing of the files with their attributes.\n");
  printf("\n");
  printf("   If you feel like you have to give money to some one for this\n");
  printf("   program, please send money to your local AIDS support group.\n");
  exit(1);	/* Thanks to Wynn Wagner for the idea. */
}else
  if (argc <3){
    strcpy(findname,argv[1]);
  } else {
    strcpy(findname,argv[2]);
  }

findflag = 0;

memset(tempname,'\0',SS);

if (findname[1] == ':')		/* if there is a drive spec'ed... */
  strncpy(tempname,findname,2);

strcat(tempname,"\\*.*\0");

while(find(tempname,&xfbuf,VO)) {
  strcpy(filename,xfbuf.name);
  if (filename[8] == '.'){	/* Volume names are returned in a */
    y = strlen(filename);	/* XXXXXXXX.XXX format.  Strip the '.'. */
    for( x = 8; x < y; x++)
      filename[x] = filename[x+1];
  }   
  printf("             Volume name is \"%s\"\n",filename);
  flag = TRUE;
  break;
}
if (flag == FALSE){
  printf("             Volume name not found.\n");
}

printf("A = Archive, H = Hidden, S = System, R = Read only, D = subDirectory\n");
printf("    Filename    Atrib   Size     Date       Time\n");
printf("  ------------  -----  ------  --------  ----------\n");

findflag = 0;
while (find(findname,&xfbuf,RO+HI+SY+DI+AR)) {
  strcpy(filename,xfbuf.name);   	/* get the found file name */
  printf("  %s",filename);
  for(i=0;i <= 13-strlen(filename);i++){
    printf(" ");			/* make the table nice and pretty */
  }

  att = getatt(filename);		/* get the attribute byte */
  att = att & ~(DI | VO);  /* should zero these out or we will get an error */

  if (argc == 3){
    switch (argv[1][0]){
      case '+':
        if (argv[1][1] == 'a'){
          putatt(filename, att | AR);
        }
        if (argv[1][1] == 'h'){
          putatt(filename, att | HI);
        }
        if (argv[1][1] == 'r'){
          putatt(filename, att | RO);
        }
        if (argv[1][1] == 's'){
          putatt(filename, att | SY);
        }
        if (argv[1][1] == 'w'){
          putatt(filename, att & (~RO));
        }
        break;

      case '-':
        if (argv[1][1] == 'a'){
          putatt(filename, att & (~AR));
        }
        if (argv[1][1] == 'h'){
          putatt(filename, att & (~HI));
        }
        if (argv[1][1] == 'r'){
          putatt(filename, att & (~RO));
        }
        if (argv[1][1] == 's'){
          putatt(filename, att & (~SY));
        }
        if (argv[1][1] == 'w'){
          putatt(filename, att | RO);
        }
        break;

      default:
        printf("I don't recognize %s as a valid change switch.",argv[1]);
        exit(1);

    }
  }

  att = getatt(filename);

  if (att & AR) printf("A"); else printf(".");
  if (att & HI) printf("H"); else printf(".");
  if (att & SY) printf("S"); else printf(".");
  if (att & RO) printf("R"); else printf(".");
  if (att & DI) printf("D"); else printf(".");

  printf(" %7lu ",xfbuf.fsize);

  /* This is the unpacker for Messy-DOS packed time and date ints. */
  year = xfbuf.date >> 9;
  month = (xfbuf.date >> 5) & 15;
  day = xfbuf.date & 31;
  printf(" %2u-%02u-%02u ",month,day,year+80);

  hour = xfbuf.time >> 11;
  minute = (xfbuf.time >> 5) & 63;
  second = (xfbuf.time & 31) << 1;
  if (hour > 12){
    printf(" %2u:%02u:%02upm ",hour-12,minute,second);
  }else{
    printf(" %2u:%02u:%02uam ",hour,minute,second);
  }
  printf("\n");
}

exit(0);

} /* end main */


find(pathname,pxfbuf,attrib)
char *pathname;
struct _xfbuf *pxfbuf;
int attrib;
{
union REGS inregs, outregs;
unsigned int seg_val;
unsigned int off_val;
int errfound;

seg_val = FP_SEG(pxfbuf);
off_val = FP_OFF(pxfbuf);	/* get the address of the structure */

inregs.x.dx = off_val;
inregs.h.ah = 26;
intdos(&inregs,&outregs);       /* set up DTA */

inregs.x.dx = FP_OFF(pathname);
inregs.x.cx = attrib;	/* the search attributes */
if (findflag == 0) {
	inregs.h.ah = 78; 	/* if this is the first time FIND FIRST */
	findflag = 1;
} else {
	inregs.h.ah = 79; 	/* if this is not the first time FIND NEXT */
}
 
intdos(&inregs,&outregs);

errfound = outregs.x.ax;

if (errfound)
  return (0);

return(1);

}

/*
   Get attribute byte from filename.
 */
getatt(name)
char *name;
{
union REGS inregs, outregs;

inregs.x.dx = FP_OFF(name);
inregs.h.ah = 67;
inregs.h.al = 0;
intdos(&inregs,&outregs);

return(outregs.x.cx);
}

/*
   Put attribute byte with filename.
*/
putatt(name,attribute)
char *name;
int attribute;
{
union REGS inregs, outregs;

inregs.x.dx = FP_OFF(name);
inregs.x.cx = attribute;
inregs.h.ah = 67;
inregs.h.al = 1;
intdos(&inregs,&outregs);
if (outregs.x.cflag){		/* This should never occur */
  printf("\nThe error number %d occurred when changing the attribute of %s.\n",
outregs.x.ax,name);
  exit(1);
}
return(outregs.x.ax);
}


-- 
Tim Pozar    Try also...
Internet: uunet!hoptoad!kumr!pozar  Fido: 1:125/555  PaBell: (415) 788-3904
        USNail:  KKSF / 77 Maiden Lane /  San Francisco CA 94108