home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Source Code 1993 July / THE_SOURCE_CODE_CD_ROM.iso / bsd_srcs / usr.sbin / mtree / create.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-05-20  |  7.7 KB  |  290 lines

  1. /*-
  2.  * Copyright (c) 1989 The Regents of the University of California.
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  * 3. All advertising materials mentioning features or use of this software
  14.  *    must display the following acknowledgement:
  15.  *    This product includes software developed by the University of
  16.  *    California, Berkeley and its contributors.
  17.  * 4. Neither the name of the University nor the names of its contributors
  18.  *    may be used to endorse or promote products derived from this software
  19.  *    without specific prior written permission.
  20.  *
  21.  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
  22.  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  23.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  24.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
  25.  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  26.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  27.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  28.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
  29.  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
  30.  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  31.  * SUCH DAMAGE.
  32.  */
  33.  
  34. #ifndef lint
  35. static char sccsid[] = "@(#)create.c    5.19 (Berkeley) 3/2/92";
  36. #endif /* not lint */
  37.  
  38. #include <sys/param.h>
  39. #include <sys/stat.h>
  40. #include <time.h>
  41. #include <fcntl.h>
  42. #include <fts.h>
  43. #include <dirent.h>
  44. #include <grp.h>
  45. #include <pwd.h>
  46. #include <errno.h>
  47. #include <unistd.h>
  48. #include <stdio.h>
  49. #include "mtree.h"
  50. #include "extern.h"
  51.  
  52. #define    INDENTNAMELEN    15
  53. #define    MAXLINELEN    80
  54.  
  55. extern int crc_total, ftsoptions;
  56. extern int dflag, sflag;
  57. extern u_short keys;
  58. extern char fullpath[MAXPATHLEN];
  59.  
  60. static gid_t gid;
  61. static uid_t uid;
  62. static mode_t mode;
  63.  
  64. static int    dsort __P((const FTSENT **, const FTSENT **));
  65. static void    output __P((int *, const char *, ...));
  66. static int    statd __P((FTS *, FTSENT *, uid_t *, gid_t *, mode_t *));
  67. static void    statf __P((FTSENT *));
  68.  
  69. void
  70. cwalk()
  71. {
  72.     register FTS *t;
  73.     register FTSENT *p;
  74.     time_t clock;
  75.     char *argv[2], host[MAXHOSTNAMELEN];
  76.  
  77.     (void)time(&clock);
  78.     (void)gethostname(host, sizeof(host));
  79.     (void)printf(
  80.         "#\t   user: %s\n#\tmachine: %s\n#\t   tree: %s\n#\t   date: %s",
  81.         getlogin(), host, fullpath, ctime(&clock));
  82.  
  83.     argv[0] = ".";
  84.     argv[1] = NULL;
  85.     if ((t = fts_open(argv, ftsoptions, dsort)) == NULL)
  86.         err("fts_open: %s", strerror(errno));
  87.     while (p = fts_read(t))
  88.         switch(p->fts_info) {
  89.         case FTS_D:
  90.             (void)printf("\n# %s\n", p->fts_path);
  91.             statd(t, p, &uid, &gid, &mode);
  92.             statf(p);
  93.             break;
  94.         case FTS_DP:
  95.             if (p->fts_level > 0)
  96.                 (void)printf("# %s\n..\n\n", p->fts_path);
  97.             break;
  98.         case FTS_DNR:
  99.         case FTS_ERR:
  100.         case FTS_NS:
  101.             (void)fprintf(stderr,
  102.                 "mtree: %s: %s\n", p->fts_path, strerror(errno));
  103.             break;
  104.         default:
  105.             if (!dflag)
  106.                 statf(p);
  107.             break;
  108.             
  109.         }
  110.     (void)fts_close(t);
  111.     if (sflag && keys & F_CKSUM)
  112.         (void)fprintf(stderr,
  113.             "mtree: %s checksum: %lu\n", fullpath, crc_total);
  114. }
  115.  
  116. static void
  117. statf(p)
  118.     FTSENT *p;
  119. {
  120.     struct group *gr;
  121.     struct passwd *pw;
  122.     u_long len, val;
  123.     int fd, indent;
  124.  
  125.     if (S_ISDIR(p->fts_statp->st_mode))
  126.         indent = printf("%s", p->fts_name); 
  127.     else
  128.         indent = printf("    %s", p->fts_name);
  129.  
  130.     if (indent > INDENTNAMELEN)
  131.         indent = MAXLINELEN;
  132.     else
  133.         indent += printf("%*s", INDENTNAMELEN - indent, "");
  134.  
  135.     if (!S_ISREG(p->fts_statp->st_mode))
  136.         output(&indent, "type=%s", inotype(p->fts_statp->st_mode));
  137.     if (keys & (F_UID | F_UNAME) && p->fts_statp->st_uid != uid)
  138.         if (keys & F_UNAME && (pw = getpwuid(p->fts_statp->st_uid)))
  139.             output(&indent, "uname=%s", pw->pw_name);
  140.         else /* if (keys & F_UID) */
  141.             output(&indent, "uid=%u", p->fts_statp->st_uid);
  142.     if (keys & (F_GID | F_GNAME) && p->fts_statp->st_gid != gid)
  143.         if (keys & F_GNAME && (gr = getgrgid(p->fts_statp->st_gid)))
  144.             output(&indent, "gid=%s", gr->gr_name);
  145.         else /* if (keys & F_GID) */
  146.             output(&indent, "gid=%u", p->fts_statp->st_gid);
  147.     if (keys & F_MODE && (p->fts_statp->st_mode & MBITS) != mode)
  148.         output(&indent, "mode=%#o", p->fts_statp->st_mode & MBITS);
  149.     if (keys & F_NLINK && p->fts_statp->st_nlink != 1)
  150.         output(&indent, "nlink=%u", p->fts_statp->st_nlink);
  151.     if (keys & F_SIZE)
  152.         output(&indent, "size=%ld", p->fts_statp->st_size);
  153.     if (keys & F_TIME)
  154.         output(&indent, "time=%ld", p->fts_statp->st_mtime);
  155.     if (keys & F_CKSUM && S_ISREG(p->fts_statp->st_mode)) {
  156.         if ((fd = open(p->fts_accpath, O_RDONLY, 0)) < 0 ||
  157.             crc(fd, &val, &len))
  158.             err("%s: %s", p->fts_accpath, strerror(errno));
  159.         (void)close(fd);
  160.         output(&indent, "cksum=%lu", val);
  161.     }
  162.     if (keys & F_SLINK &&
  163.         (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE))
  164.         output(&indent, "link=%s", rlink(p->fts_accpath));
  165.     (void)putchar('\n');
  166. }
  167.  
  168. #define    MAXGID    5000
  169. #define    MAXUID    5000
  170. #define    MAXMODE    MBITS + 1
  171.  
  172. static int
  173. statd(t, parent, puid, pgid, pmode)
  174.     FTS *t;
  175.     FTSENT *parent;
  176.     uid_t *puid;
  177.     gid_t *pgid;
  178.     mode_t *pmode;
  179. {
  180.     register FTSENT *p;
  181.     register gid_t sgid;
  182.     register uid_t suid;
  183.     register mode_t smode;
  184.     struct group *gr;
  185.     struct passwd *pw;
  186.     gid_t savegid;
  187.     uid_t saveuid;
  188.     mode_t savemode;
  189.     u_short maxgid, maxuid, maxmode, g[MAXGID], u[MAXUID], m[MAXMODE];
  190.  
  191.     if ((p = fts_children(t, 0)) == NULL) {
  192.         if (errno)
  193.             err("%s: %s", RP(parent), strerror(errno));
  194.         return (1);
  195.     }
  196.  
  197.     bzero(g, sizeof(g));
  198.     bzero(u, sizeof(u));
  199.     bzero(m, sizeof(m));
  200.  
  201.     maxuid = maxgid = maxmode = 0;
  202.     for (; p; p = p->fts_link) {
  203.         smode = p->fts_statp->st_mode & MBITS;
  204.         if (smode < MAXMODE && ++m[smode] > maxmode) {
  205.             savemode = smode;
  206.             maxmode = m[smode];
  207.         }
  208.         sgid = p->fts_statp->st_gid;
  209.         if (sgid < MAXGID && ++g[sgid] > maxgid) {
  210.             savegid = sgid;
  211.             maxgid = g[sgid];
  212.         }
  213.         suid = p->fts_statp->st_uid;
  214.         if (suid < MAXUID && ++u[suid] > maxuid) {
  215.             saveuid = suid;
  216.             maxuid = u[suid];
  217.         }
  218.     }
  219.     (void)printf("/set type=file");
  220.     if (keys & F_GID)
  221.         (void)printf(" gid=%u", savegid);
  222.     if (keys & F_GNAME)
  223.         if ((gr = getgrgid(savegid)) != NULL)
  224.             (void)printf(" gname=%s", gr->gr_name);
  225.         else
  226.             (void)printf(" gid=%u", savegid);
  227.     if (keys & F_UNAME)
  228.         if ((pw = getpwuid(saveuid)) != NULL)
  229.             (void)printf(" uname=%s", pw->pw_name);
  230.         else
  231.             (void)printf(" uid=%u", saveuid);
  232.     if (keys & F_UID)
  233.         (void)printf(" uid=%u", saveuid);
  234.     if (keys & F_MODE)
  235.         (void)printf(" mode=%#o", savemode);
  236.     if (keys & F_NLINK)
  237.         (void)printf(" nlink=1");
  238.     (void)printf("\n");
  239.     *puid = saveuid;
  240.     *pgid = savegid;
  241.     *pmode = savemode;
  242.     return (0);
  243. }
  244.  
  245. static int
  246. dsort(a, b)
  247.     const FTSENT **a, **b;
  248. {
  249.     if (S_ISDIR((*a)->fts_statp->st_mode)) {
  250.         if (!S_ISDIR((*b)->fts_statp->st_mode))
  251.             return (1);
  252.     } else if (S_ISDIR((*b)->fts_statp->st_mode))
  253.         return (-1);
  254.     return (strcmp((*a)->fts_name, (*b)->fts_name));
  255. }
  256.  
  257. #if __STDC__
  258. #include <stdarg.h>
  259. #else
  260. #include <varargs.h>
  261. #endif
  262.  
  263. void
  264. #if __STDC__
  265. output(int *offset, const char *fmt, ...)
  266. #else
  267. output(offset, fmt, va_alist)
  268.     int *offset;
  269.     char *fmt;
  270.         va_dcl
  271. #endif
  272. {
  273.     va_list ap;
  274.     int len;
  275.     char buf[1024];
  276. #if __STDC__
  277.     va_start(ap, fmt);
  278. #else
  279.     va_start(ap);
  280. #endif
  281.     len = vsnprintf(buf, sizeof(buf), fmt, ap);
  282.     va_end(ap);
  283.  
  284.     if (*offset + len > MAXLINELEN - 3) {
  285.         (void)printf(" \\\n%*s", INDENTNAMELEN, "");
  286.         *offset = INDENTNAMELEN;
  287.     }
  288.     *offset += printf(" %s", buf) + 1;
  289. }
  290.