home *** CD-ROM | disk | FTP | other *** search
/ The Developer Connection…ice Driver Kit for OS/2 3 / DEV3-D1.ISO / source / util2src / chmod.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-07-24  |  15.3 KB  |  377 lines

  1. /*============================================================================*
  2.  * main() module: chmod.c - Change file mode.
  3.  *
  4.  * (C)Copyright IBM Corporation, 1991, 1992.                     Brian E. Yoder
  5.  *
  6.  * This program is a loose adaptation of the AIX 'chmod' command.  It changes
  7.  * a file's attributes (mode).  Unlike the DOS ATTRIB command, it allows you
  8.  * to change the mode of system and hidden files and directories.
  9.  *
  10.  * This program views a "readonly" file as having no write capability and
  11.  * NOT as having readonly capability.  DOS and OS/2 seem to me to be a
  12.  * bit odd in their treatment of 'readonly' as a capability!
  13.  *
  14.  * However, a "hidden" file, although excluded from directory searches by
  15.  * the DIR, COPY, and other commands, is perfectly readable by the open()
  16.  * subroutine:  I can look at the hidden '\ibmdos.com' file using the E3
  17.  * editor.  A hidden file does NOT lack the capability of being read.
  18.  *
  19.  * The chmod() library call only lets you set/reset the readonly attribute.
  20.  * Therefore, the DOS-only _dos_setfileattr() subroutine is used to set
  21.  * file attributes.
  22.  *
  23.  * See the chmod.doc file for more information on use and examples.
  24.  *
  25.  * 04/18/91 - Created.
  26.  * 04/19/91 - Version 1.0 - We cannot change the attributes of a directory.
  27.  * 04/30/91 - Version 1.0 - Ported to OS/2.
  28.  * 05/06/91 - Version 1.1 - Updated per new slrewind() interface in speclist.c.
  29.  * 05/09/91 - Version 1.2 - Support new interface to slmake(): Don't append
  30.  *                          "\*" to end of fspecs that are directory names.
  31.  * 11/20/91 - Version 1.3 - Support -R to recursively descend directories.
  32.  * 07/24/92 - Version 1.3 - For OS/2 2.0 and C Set/2. pathmode is uint.
  33.  *============================================================================*/
  34.  
  35. static char copr[] = "(c)Copyright IBM Corp, 1991, 1992.  All rights reserved.";
  36. static char ver[]  = "Version 1.3  07/24/91";
  37.  
  38. #include <stdio.h>
  39. #include <stdlib.h>
  40. #include <string.h>
  41. #include <sys/types.h>
  42.  
  43. #include "util.h"
  44.  
  45. #define NO       0
  46. #define YES      1
  47.  
  48. static  char     buff[2048+1];      /* Buffer for output filenames */
  49.  
  50. /*============================================================================*
  51.  * Define internal functions to allow forward access
  52.  *============================================================================*/
  53.  
  54. static void       syntax       ( void );
  55. static int        fchmod       ( char *, uint, char, int, int, int, int );
  56.  
  57. /*============================================================================*
  58.  * Main Program Entry Point
  59.  *============================================================================*/
  60.  
  61. main(argc, argv)
  62.  
  63. int argc;                           /* arg count */
  64. char *argv[];                       /* arg pointers */
  65.  
  66. {
  67.   int     rc;                       /* Return code store area */
  68.   long    lrc;                      /* Long return code */
  69.   char   *modespec;                 /* Pointer to mode specification string */
  70.   char    cf;                       /* Current flag character (if any) */
  71.  
  72.   char    opchar;                   /* Operation char: +-= */
  73.   int     w_mode;                   /* Mode settings */
  74.   int     s_mode;
  75.   int     h_mode;
  76.   int     a_mode;
  77.  
  78.   SLPATH *speclist;                 /* Pointer to linked list of path specs */
  79.   ushort  mflags;                   /* Match flags for slrewind() */
  80.   ushort  recurse = FALSE;          /* Recursive directory descent? */
  81.  
  82.   FINFO  *fdata;                    /* Pointers returned by slmatch() */
  83.   SLPATH *pdata;
  84.   SLNAME *ndata;
  85.  
  86.  /*---------------------------------------------------------------------------*
  87.   * Check arguments
  88.   *---------------------------------------------------------------------------*/
  89.  
  90.   argc--;                           /* Ignore 1st argument (program name) */
  91.   argv++;
  92.  
  93.   if (argc != 0)                    /* If we have at least one argument: (v1.3) */
  94.   {
  95.      if (strcmpi(*argv, "-R") == 0)      /* If it's -R: */
  96.      {
  97.         recurse = TRUE;                       /* Set flag to allow dir descent */
  98.         argc--;                               /* And throw away the flag */
  99.         argv++;
  100.      }                                   /* endif */
  101.   }                                 /* endif */
  102.  
  103.   if (argc < 2)                     /* If we don't have enough arguments: */
  104.      syntax();                           /* Display syntax and exit */
  105.  
  106.   modespec = *argv;                 /* 1st argument is mode specification */
  107.   argc--;                           /* Remaining args are file specs */
  108.   argv++;
  109.  
  110.  /*---------------------------------------------------------------------------*
  111.   * Process mode specification and store in 'opchar' and 'modeset'
  112.   *
  113.   * Initially, we will set the readonly bit if 'w' is specified and leave it
  114.   * 0 if 'w' is not specified.  Once 'modeset' has been set up, we will
  115.   * invert the readonly bit before continuing on.
  116.   *---------------------------------------------------------------------------*/
  117.  
  118.   w_mode = FALSE;                   /* Initialize modes to 'not specified' */
  119.   s_mode = FALSE;
  120.   h_mode = FALSE;
  121.   a_mode = FALSE;
  122.  
  123.   opchar = *modespec;               /* Check first char: operation: */
  124.   switch (opchar)
  125.   {
  126.      case '-':                           /* It must be one of these */
  127.      case '+':
  128.      case '=':
  129.         break;
  130.      default:                            /* Anything else is an error */
  131.         syntax();
  132.         break;
  133.   }
  134.  
  135.   modespec++;                       /* Bump modespec past the operation */
  136.   cf = *modespec;                   /* Store first mode letter specified */
  137.   if (cf == '\0') syntax();         /* If none: error */
  138.  
  139.   while (cf != '\0')                /* For each mode letter: */
  140.   {
  141.      switch(cf)                          /* Check mode letter and update mode */
  142.      {                                   /* setting appropriately */
  143.         case 'w':
  144.            w_mode = TRUE;
  145.            break;
  146.         case 's':
  147.            s_mode = TRUE;
  148.            break;
  149.         case 'h':
  150.            h_mode = TRUE;
  151.            break;
  152.         case 'a':
  153.            a_mode = TRUE;
  154.            break;
  155.         default:                            /* Anything else is an error */
  156.            syntax();
  157.            break;
  158.      }
  159.      modespec++;                         /* Point to next mode letter */
  160.      cf = *modespec;                     /* And store it in cf */
  161.   }
  162.  
  163.  /*---------------------------------------------------------------------------*
  164.   * Process file specifications and build specification list
  165.   *---------------------------------------------------------------------------*/
  166.  
  167.   rc = slmake(&speclist, TRUE, FALSE, argc, argv);
  168.  
  169.   if (rc != 0)                      /* If there was an error: */
  170.   {                                 /* Analyze rc, show msg, and return */
  171.      if (rc == REGX_MEMORY)
  172.         fprintf(stderr, "Out of memory while processing '%s'.\n",
  173.            slerrspec());
  174.      else
  175.         fprintf(stderr, "Invalid filespec: '%s'.\n",
  176.            slerrspec());
  177.  
  178.      return(2);
  179.   }
  180.  
  181.  /*---------------------------------------------------------------------------*
  182.   * Attempt to match files to the specification list
  183.   *---------------------------------------------------------------------------*/
  184.  
  185.   mflags = 0;                       /* Set list of files to match to include: */
  186.   mflags = mflags | SL_NORMAL |          /* Ordinary files */
  187.                     SL_HIDDEN |          /* Hidden files */
  188.                     SL_SYSTEM;           /* System files */
  189.  
  190.   slrewind(speclist, mflags, recurse);/* Initialize slmatch() */
  191.   for (;;)                          /* Loop to find all matching DOS files: */
  192.   {
  193.      fdata = slmatch(&pdata,             /* Get next matching DOS file */
  194.                      &ndata);
  195.      if (fdata == NULL)                  /* If none: */
  196.         break;                                /* Done */
  197.  
  198.      strcpy(buff, pdata->path);          /* Store path portion of filename */
  199.      pathcat(buff, fdata->achName);      /* Add name to end of path string */
  200.  
  201.      rc = fchmod(buff, fdata->attrFile,  /* Set new mode for file */
  202.                  opchar, w_mode,
  203.                          s_mode,
  204.                          h_mode,
  205.                          a_mode);
  206.  
  207.      if (rc != 0)                        /* If error: Dipslay and continue */
  208.         fprintf(stderr, "chmod: Can't change mode for '%s'\n", buff);
  209.   }
  210.  
  211.  /*---------------------------------------------------------------------------*
  212.   * Display (on stderr) all filespecs that had no matching files
  213.   *---------------------------------------------------------------------------*/
  214.  
  215.   lrc = slnotfound(speclist);       /* Display path\names w/no matching files */
  216.   if (lrc == 0L)                    /* If all fspecs were matched: */
  217.      return(0);                          /* Return successfully */
  218.   else                              /* Otherwise:  One or more not found: */
  219.      return(2);                          /* Return with error */
  220.  
  221. } /* end of main() */
  222.  
  223. /*============================================================================*
  224.  * syntax() - Display command syntax and exit to operating system!
  225.  *============================================================================*/
  226. static void syntax(void)
  227. {
  228.   fprintf(stderr, "%s\n", ver);
  229.   fprintf(stderr, "Usage:  chmod [-R] [+-=][wsha] fspec ...\n");
  230.   fprintf(stderr, "\n");
  231.   fprintf(stderr, "Exactly one file mode operator must be followed by one or more\n");
  232.   fprintf(stderr, "file more mode letters, with no intervening spaces.  One or more\n");
  233.   fprintf(stderr, "file specifications must follow.  All files, including system and\n");
  234.   fprintf(stderr, "hidden files, that match the file specification(s) are processed.\n");
  235.   fprintf(stderr, "Directories and volume IDs are ignored.\n");
  236.   fprintf(stderr, "\n");
  237.   fprintf(stderr, "The file mode operator can be one of the following:\n");
  238.   fprintf(stderr, "  +  Set the specified file mode(s).\n");
  239.   fprintf(stderr, "  -  Reset the specified file mode(s).\n");
  240.   fprintf(stderr, "  =  Set the specified file mode(s) and reset those not specified.\n");
  241.   fprintf(stderr, "\n");
  242.   fprintf(stderr, "The file modes that can be specified are:\n");
  243.   fprintf(stderr, "  w  Write permission.\n");
  244.   fprintf(stderr, "  s  System attribute.\n");
  245.   fprintf(stderr, "  h  Hidden attribute.\n");
  246.   fprintf(stderr, "  a  Archive attribute.\n");
  247.   fprintf(stderr, "\n");
  248.   exit(1);
  249. }
  250.  
  251. /*============================================================================*
  252.  * fchmod() - Change file's mode (attributes).        For DOS Only
  253.  *
  254.  * REMARKS:
  255.  *   This subroutine changes the attributes for the specified file or
  256.  *   directory, depending upon the operation.  The write permission,
  257.  *   system attribute, hidden attribute, and archive bit are specified
  258.  *   by the w, s, h, and a flags, respectively.  A value of TRUE means
  259.  *   the flag was specified; FALSE means it was omitted.
  260.  *
  261.  *   The opchar tells what to do with the flags:
  262.  *      + means set the attributes whose flags are TRUE.  For example,
  263.  *        if the opchar is + and only the a flag is TRUE, then the archive
  264.  *        bit will be set for the specified file.
  265.  *
  266.  *      - means to reset the attributes whose flags are TRUE.
  267.  *
  268.  *      = means to set the attributes whose flags are TRUE and reset the
  269.  *        attributes whose flags are FALSE.
  270.  *
  271.  *   The bits in the pathmode variable are defined by the _A_ #defines
  272.  *   in <dos.h>.  Only the following file attributes are processed:
  273.  *       _A_RDONLY
  274.  *       _A_SYSTEM
  275.  *       _A_HIDDEN
  276.  *       _A_ARCH
  277.  *
  278.  * RETURNS:
  279.  *   0: Successful.
  280.  *   Other: error.
  281.  *============================================================================*/
  282.  
  283. static int fchmod(
  284.  
  285. char    *path      ,                /* Path/name of file or directory */
  286. uint     pathmode  ,                /* Current file mode */
  287. char     opchar    ,                /* Operation: - + or = */
  288. int      w         ,                /* Modes specified: write (NOT readonly) */
  289. int      s         ,                /*                  system */
  290. int      h         ,                /*                  hidden */
  291. int      a         )                /*                  archive */
  292.  
  293. {
  294.   int   rc;                         /* Return code storage */
  295.  
  296. /*printf("Before: pathmode = 0x%04X\n", pathmode);*/
  297.  
  298.  /*---------------------------------------------------------------------------*
  299.   * Depending upon opchar and the flags, alter the file's attributes that are
  300.   * stored in 'pathmode'.  To set an attribute, OR its _A_ label with the
  301.   * current mode.  To reset an attribute, AND the bit-wise inversion of
  302.   * its _A_ label.  To get the bit-wise inversion of a label, exclusive OR the
  303.   * label with 0xFFFF.
  304.   *
  305.   * Note:  To set write permission, we must reset the readonly bit.  To remove
  306.   * write permission, we must set the readonly bit.
  307.   *---------------------------------------------------------------------------*/
  308.  
  309.   switch (opchar)                   /* Depending upon the operation: */
  310.   {
  311.      case '+':
  312.        /*------------------------------------------------------------*
  313.         * Set the specified attributes
  314.         *------------------------------------------------------------*/
  315.         if (w)
  316.            pathmode = pathmode & (0xFFFFFFFF ^ _A_RDONLY);
  317.         if (s)
  318.            pathmode = pathmode | _A_SYSTEM;
  319.         if (h)
  320.            pathmode = pathmode | _A_HIDDEN;
  321.         if (a)
  322.            pathmode = pathmode | _A_ARCH;
  323.         break;
  324.  
  325.      case '-':
  326.        /*------------------------------------------------------------*
  327.         * Reset the specified attributes
  328.         *------------------------------------------------------------*/
  329.         if (w)
  330.            pathmode = pathmode | _A_RDONLY;
  331.         if (s)
  332.            pathmode = pathmode & (0xFFFFFFFF ^ _A_SYSTEM);
  333.         if (h)
  334.            pathmode = pathmode & (0xFFFFFFFF ^ _A_HIDDEN);
  335.         if (a)
  336.            pathmode = pathmode & (0xFFFFFFFF ^ _A_ARCH);
  337.         break;
  338.  
  339.        /*------------------------------------------------------------*
  340.         * Set the specified attributes and reset those not specified
  341.         *------------------------------------------------------------*/
  342.      case '=':
  343.         if (w)
  344.            pathmode = pathmode & (0xFFFFFFFF ^ _A_RDONLY);
  345.         else
  346.            pathmode = pathmode | _A_RDONLY;
  347.  
  348.         if (s)
  349.            pathmode = pathmode | _A_SYSTEM;
  350.         else
  351.            pathmode = pathmode & (0xFFFFFFFF ^ _A_SYSTEM);
  352.  
  353.         if (h)
  354.            pathmode = pathmode | _A_HIDDEN;
  355.         else
  356.            pathmode = pathmode & (0xFFFFFFFF ^ _A_HIDDEN);
  357.  
  358.         if (a)
  359.            pathmode = pathmode | _A_ARCH;
  360.         else
  361.            pathmode = pathmode & (0xFFFFFFFF ^ _A_ARCH);
  362.         break;
  363.   }
  364.  
  365. /*printf("After:  pathmode = 0x%04X\n", pathmode);*/
  366.  
  367.  /*---------------------------------------------------------------------------*
  368.   * Change the file's attributes to the value stored in 'pathmode'
  369.   *---------------------------------------------------------------------------*/
  370.  
  371. //rc = _dos_setfileattr(path, pathmode);           /* DOS */
  372. //rc = DosSetFileMode(path, pathmode, 0L);         /* OS/2 16-bit */
  373.   rc = SetFileMode(path, pathmode);                /* OS/2 32-bit */
  374.  
  375.   return(rc);
  376. }
  377.