chiark / gitweb /
checkpath.c: Move the message buffer into the state structure.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 17 Jul 2024 12:16:03 +0000 (13:16 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 17 Jul 2024 12:23:10 +0000 (13:23 +0100)
Rather invasive, but not super complicated.

checkpath.c

index 8a19ae5cdd84df10f32c85c4c91bcf08c0735708..2cb73cda2fec3dd09839403ffd76018eb7901ee9 100644 (file)
@@ -69,6 +69,7 @@ struct state {
   struct elt *sp;                      /* Stack pointer for list */
   dstr path;                           /* Current path string */
   dstr link;                           /* Symbolic link target string */
   struct elt *sp;                      /* Stack pointer for list */
   dstr path;                           /* Current path string */
   dstr link;                           /* Symbolic link target string */
+  dstr msg;                            /* Message string */
 };
 
 /*----- Static variables --------------------------------------------------*/
 };
 
 /*----- Static variables --------------------------------------------------*/
@@ -183,7 +184,8 @@ static void push(struct state *state, struct elt *e)
 
 /* --- @report@ --- *
  *
 
 /* --- @report@ --- *
  *
- * Arguments:  @const struct checkpath *cp@ = pointer to query
+ * Arguments:  @struct state *state@ = pointer to state
+ *             @const struct checkpath *cp@ = pointer to query
  *             @unsigned what@ = what sort of report is this?
  *             @int verbose@ = how verbose is this?
  *             @const char *p@ = what path does it refer to?
  *             @unsigned what@ = what sort of report is this?
  *             @int verbose@ = how verbose is this?
  *             @const char *p@ = what path does it refer to?
@@ -194,10 +196,10 @@ static void push(struct state *state, struct elt *e)
  * Use:                Formats and presents messages to the client.
  */
 
  * Use:                Formats and presents messages to the client.
  */
 
-static void report(const struct checkpath *cp, unsigned what, int verbose,
+static void report(struct state *state, const struct checkpath *cp,
+                  unsigned what, int verbose,
                   const char *p, const char *msg, ...)
 {
                   const char *p, const char *msg, ...)
 {
-  dstr d = DSTR_INIT;
   va_list ap;
   const char *q = msg;
   const char *s;
   va_list ap;
   const char *q = msg;
   const char *s;
@@ -222,56 +224,56 @@ static void report(const struct checkpath *cp, unsigned what, int verbose,
 
   /* --- Format the message nicely --- */
 
 
   /* --- Format the message nicely --- */
 
+  dstr_reset(&state->msg);
   va_start(ap, msg);
   if (verbose > 1)
   va_start(ap, msg);
   if (verbose > 1)
-    dstr_puts(&d, "[ ");
+    dstr_puts(&state->msg, "[ ");
   if (p)
   if (p)
-    dstr_putf(&d, "Path: %s: ", p);
+    dstr_putf(&state->msg, "Path: %s: ", p);
   while (*q) {
     if (*q == '%') {
       q++;
       switch (*q) {
        case 'e':
   while (*q) {
     if (*q == '%') {
       q++;
       switch (*q) {
        case 'e':
-         dstr_puts(&d, strerror(e));
+         dstr_puts(&state->msg, strerror(e));
          break;
        case 'u':
          break;
        case 'u':
-         u = (uid_t)va_arg(ap, int);
+         u = (uid_t)va_arg(ap, long);
          if ((pw = getpwuid(u)) != 0)
          if ((pw = getpwuid(u)) != 0)
-           dstr_putf(&d, "`%s'", pw->pw_name);
+           dstr_putf(&state->msg, "`%s'", pw->pw_name);
          else
          else
-           dstr_putf(&d, "%i", (int)u);
+           dstr_putf(&state->msg, "#%ld", (long)u);
          break;
        case 'g':
          break;
        case 'g':
-         g = (gid_t)va_arg(ap, int);
+         g = (gid_t)va_arg(ap, long);
          if ((gr = getgrgid(g)) != 0)
          if ((gr = getgrgid(g)) != 0)
-           dstr_putf(&d, "`%s'", gr->gr_name);
+           dstr_putf(&state->msg, "`%s'", gr->gr_name);
          else
          else
-           dstr_putf(&d, "%i", (int)g);
+           dstr_putf(&state->msg, "#%ld", (long)g);
          break;
        case 's':
          s = va_arg(ap, const char *);
          break;
        case 's':
          s = va_arg(ap, const char *);
-         dstr_puts(&d, s);
+         dstr_puts(&state->msg, s);
          break;
        case '%':
          break;
        case '%':
-         dstr_putc(&d, '%');
+         dstr_putc(&state->msg, '%');
          break;
        default:
          break;
        default:
-         dstr_putc(&d, '%');
-         dstr_putc(&d, *q);
+         dstr_putc(&state->msg, '%');
+         dstr_putc(&state->msg, *q);
          break;
       }
       q++;
     } else {
       n = strcspn(q, "%");
          break;
       }
       q++;
     } else {
       n = strcspn(q, "%");
-      DPUTM(&d, q, n);
+      DPUTM(&state->msg, q, n);
       q += n;
     }
   }
   if (verbose > 1)
       q += n;
     }
   }
   if (verbose > 1)
-    dstr_puts(&d, " ]");
-  DPUTZ(&d);
-  cp->cp_report(what, verbose, p, d.buf, cp->cp_arg);
-  dstr_destroy(&d);
+    dstr_puts(&state->msg, " ]");
+  DPUTZ(&state->msg);
+  cp->cp_report(what, verbose, p, state->msg.buf, cp->cp_arg);
   va_end(ap);
 }
 
   va_end(ap);
 }
 
@@ -279,6 +281,7 @@ static void report(const struct checkpath *cp, unsigned what, int verbose,
  *
  * Arguments:  @const char *p@ = name of directory to check
  *             @struct stat *st@ = pointer to @stat@(2) block for it
  *
  * Arguments:  @const char *p@ = name of directory to check
  *             @struct stat *st@ = pointer to @stat@(2) block for it
+ *             @struct state *state@ = pointer to state
  *             @const struct checkpath *cp@ = pointer to query
  *             @unsigned f@ = various flags (@SF_...@)
  *
  *             @const struct checkpath *cp@ = pointer to query
  *             @unsigned f@ = various flags (@SF_...@)
  *
@@ -292,7 +295,8 @@ static void report(const struct checkpath *cp, unsigned what, int verbose,
 #define SF_LAST 1u                     /* This is the final item to check */
 
 static unsigned sanity(const char *p, struct stat *st,
 #define SF_LAST 1u                     /* This is the final item to check */
 
 static unsigned sanity(const char *p, struct stat *st,
-                      const struct checkpath *cp, unsigned f)
+                      struct state *state, const struct checkpath *cp,
+                      unsigned f)
 {
   unsigned bad = 0;
   int stickyok = 0;
 {
   unsigned bad = 0;
   int stickyok = 0;
@@ -308,7 +312,7 @@ static unsigned sanity(const char *p, struct stat *st,
   if ((cp->cp_what & CP_WRWORLD) &&
       (st->st_mode & (S_IWOTH | stickyok)) == S_IWOTH) {
     bad |= CP_WRWORLD;
   if ((cp->cp_what & CP_WRWORLD) &&
       (st->st_mode & (S_IWOTH | stickyok)) == S_IWOTH) {
     bad |= CP_WRWORLD;
-    report(cp, CP_WRWORLD, 1, p, "** world writable **");
+    report(state, cp, CP_WRWORLD, 1, p, "** world writable **");
   }
 
   /* --- Check for group-writability --- */
   }
 
   /* --- Check for group-writability --- */
@@ -326,8 +330,8 @@ static unsigned sanity(const char *p, struct stat *st,
     }
     if (b) {
       bad |= b;
     }
     if (b) {
       bad |= b;
-      report(cp, b, 1, p, "writable by %sgroup %g",
-            (b == CP_WROTHGRP) ? "other " : "", st->st_gid);
+      report(state, cp, b, 1, p, "writable by %sgroup %g",
+            (b == CP_WROTHGRP) ? "other " : "", (long)st->st_gid);
     }
   }
 
     }
   }
 
@@ -337,7 +341,8 @@ static unsigned sanity(const char *p, struct stat *st,
       st->st_uid != cp->cp_uid &&
       st->st_uid != 0) {
     bad |= CP_WROTHUSR;
       st->st_uid != cp->cp_uid &&
       st->st_uid != 0) {
     bad |= CP_WROTHUSR;
-    report(cp, CP_WROTHUSR, 1, p, "owner is user %u", st->st_uid);
+    report(state, cp, CP_WROTHUSR, 1, p,
+          "owner is user %u", (long)st->st_uid);
   }
 
   /* --- Done sanity check --- */
   }
 
   /* --- Done sanity check --- */
@@ -374,23 +379,24 @@ unsigned checkpath(const char *p, const struct checkpath *cp)
   state->sp = (/*unconst*/ struct elt *)&rootnode;
   dstr_create(&state->path);
   dstr_create(&state->link);
   state->sp = (/*unconst*/ struct elt *)&rootnode;
   dstr_create(&state->path);
   dstr_create(&state->link);
+  dstr_create(&state->msg);
 
   /* --- Try to find the current directory --- */
 
   if (!getcwd(cwd, sizeof(cwd))) {
 
   /* --- Try to find the current directory --- */
 
   if (!getcwd(cwd, sizeof(cwd))) {
-    report(cp, CP_ERROR, 0, 0, "can't find current directory: %e");
+    report(state, cp, CP_ERROR, 0, 0, "can't find current directory: %e");
     return (CP_ERROR);
   }
 
   /* --- Check that the root directory is OK --- */
 
   if (stat("/", &st)) {
     return (CP_ERROR);
   }
 
   /* --- Check that the root directory is OK --- */
 
   if (stat("/", &st)) {
-    report(cp, CP_ERROR, 0, 0, "can't stat root directory: %e");
+    report(state, cp, CP_ERROR, 0, 0, "can't stat root directory: %e");
     return (CP_ERROR);
   }
 
     return (CP_ERROR);
   }
 
-  report(cp, CP_REPORT, 3, p, "begin scan");
-  bad |= sanity("/", &st, cp, 0);
+  report(state, cp, CP_REPORT, 3, p, "begin scan");
+  bad |= sanity("/", &st, state, cp, 0);
 
   /* --- Get the initial list of things to process --- */
 
 
   /* --- Get the initial list of things to process --- */
 
@@ -426,7 +432,7 @@ unsigned checkpath(const char *p, const struct checkpath *cp)
     /* --- Find out what sort of a thing this is --- */
 
     if (lstat(state->path.buf, &st)) {
     /* --- Find out what sort of a thing this is --- */
 
     if (lstat(state->path.buf, &st)) {
-      report(cp, CP_ERROR, 0, state->path.buf, "can't stat: %e");
+      report(state, cp, CP_ERROR, 0, state->path.buf, "can't stat: %e");
       bad |= CP_ERROR;
       break;
     }
       bad |= CP_ERROR;
       break;
     }
@@ -441,12 +447,13 @@ unsigned checkpath(const char *p, const struct checkpath *cp)
       dstr_ensure(&state->link, st.st_size + 1);
       if ((i = readlink(state->path.buf,
                        state->link.buf, state->link.sz)) < 0) {
       dstr_ensure(&state->link, st.st_size + 1);
       if ((i = readlink(state->path.buf,
                        state->link.buf, state->link.sz)) < 0) {
-       report(cp, CP_ERROR, 0, state->path.buf, "can't readlink: %e");
+       report(state, cp, CP_ERROR, 0, state->path.buf,
+              "can't readlink: %e");
        bad |= CP_ERROR;
        break;
       }
       state->link.buf[i] = 0;
        bad |= CP_ERROR;
        break;
       }
       state->link.buf[i] = 0;
-      report(cp, CP_SYMLINK, 2, state->path.buf,
+      report(state, cp, CP_SYMLINK, 2, state->path.buf,
             "symlink -> `%s'", state->link.buf);
 
       /* --- Handle sticky parents --- *
             "symlink -> `%s'", state->link.buf);
 
       /* --- Handle sticky parents --- *
@@ -460,8 +467,8 @@ unsigned checkpath(const char *p, const struct checkpath *cp)
          (state->sp->e_link->e_flags & EF_STICKY) &&
          st.st_uid != cp->cp_uid && st.st_uid != 0) {
        bad |= CP_WROTHUSR;
          (state->sp->e_link->e_flags & EF_STICKY) &&
          st.st_uid != cp->cp_uid && st.st_uid != 0) {
        bad |= CP_WROTHUSR;
-       report(cp, CP_WROTHUSR, 1, state->path.buf,
-              "symlink modifiable by user %u", st.st_uid);
+       report(state, cp, CP_WROTHUSR, 1, state->path.buf,
+              "symlink modifiable by user %u", (long)st.st_uid);
       }
 
       /* --- Sort out what to do from here --- */
       }
 
       /* --- Sort out what to do from here --- */
@@ -476,12 +483,12 @@ unsigned checkpath(const char *p, const struct checkpath *cp)
 
     /* --- Run the sanity check on this path element --- */
 
 
     /* --- Run the sanity check on this path element --- */
 
-    bad |= sanity(state->path.buf, &st, cp, ee ? 0 : SF_LAST);
+    bad |= sanity(state->path.buf, &st, state, cp, ee ? 0 : SF_LAST);
 
     if (S_ISDIR(st.st_mode)) {
       if (st.st_mode & S_ISVTX)
        state->sp->e_flags |= EF_STICKY;
 
     if (S_ISDIR(st.st_mode)) {
       if (st.st_mode & S_ISVTX)
        state->sp->e_flags |= EF_STICKY;
-      report(cp, CP_REPORT, 4, state->path.buf, "directory");
+      report(state, cp, CP_REPORT, 4, state->path.buf, "directory");
       continue;
     }
 
       continue;
     }
 
@@ -494,7 +501,7 @@ unsigned checkpath(const char *p, const struct checkpath *cp)
 
   if (ee) {
     if (!(bad & CP_ERROR))
 
   if (ee) {
     if (!(bad & CP_ERROR))
-      report(cp, CP_ERROR, 0, 0, "junk left over after reaching leaf");
+      report(state, cp, CP_ERROR, 0, 0, "junk left over after reaching leaf");
     while (ee) {
       e = ee->e_link;
       ee = e;
     while (ee) {
       e = ee->e_link;
       ee = e;
@@ -503,6 +510,7 @@ unsigned checkpath(const char *p, const struct checkpath *cp)
 
   dstr_destroy(&state->path);
   dstr_destroy(&state->link);
 
   dstr_destroy(&state->path);
   dstr_destroy(&state->link);
+  dstr_destroy(&state->msg);
   pool_destroy(state->p);
   return (bad);
 }
   pool_destroy(state->p);
   return (bad);
 }