utf8: don't allow NUL in decoded strings.
[ccan] / tools / ccanlint / tests / license_comment.c
index f1902126472c235df1e558a94e4649caa0ce021a..ef865a4d6f74fdaa51fe277dae1324e791b3513b 100644 (file)
@@ -9,13 +9,35 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <err.h>
-#include <ccan/talloc/talloc.h>
 #include <ccan/str/str.h>
-#include <ccan/str_talloc/str_talloc.h>
+#include <ccan/tal/str/str.h>
+
+/**
+ * line_has_license_flavour - returns true if line contains a <flavour> license
+ * @line: line to look for license in
+ * @shortname: license to find
+ * @note ("LGPLv2.0","LGPL") returns true
+ * @note ("LGPLv2.0","GPL") returns false
+ */
+static bool line_has_license_flavour(const char *line, const char *shortname)
+{
+       char **toks = tal_strsplit(NULL, line, " \t-:", STR_NO_EMPTY);
+       size_t i;
+       bool ret = false;
+
+       for (i = 0; toks[i] != NULL; i++) {
+               if (strstarts(toks[i], shortname)) {
+                       ret = true;
+                       break;
+               }
+       }
+       tal_free(toks);
+       return ret;
+}
 
 static void check_license_comment(struct manifest *m,
-                                 bool keep,
-                                 unsigned int *timeleft, struct score *score)
+                                 unsigned int *timeleft UNNEEDED,
+                                 struct score *score)
 {
        struct list_head *list;
 
@@ -41,8 +63,8 @@ static void check_license_comment(struct manifest *m,
                                        break;
                                if (strstr(lines[i], "LICENSE"))
                                        found_license = true;
-                               if (strstr(lines[i],
-                                          licenses[m->license].shortname))
+                               if (line_has_license_flavour(lines[i],
+                                                            licenses[m->license].shortname))
                                        found_flavor = true;
                        }
                        if ((!found_license || !found_flavor)
@@ -60,10 +82,49 @@ static void check_license_comment(struct manifest *m,
        }
 }
 
+static void add_license_comment(struct manifest *m, struct score *score)
+{
+       struct file_error *e;
+       const char *license_desc = get_license_oneliner(score, m->license);
+       char *files = tal_strdup(score, ""), *q;
+
+       list_for_each(&score->per_file_errors, e, list)
+               tal_append_fmt(&files, "  %s\n", e->file->name);
+
+       q = tal_fmt(score, "The following files don't have a comment:\n%s\n"
+                   "Should I prepend '%s'?", files, license_desc);
+       if (!ask(q))
+               return;
+
+       list_for_each(&score->per_file_errors, e, list) {
+               char *tmpname;
+               FILE *out;
+               unsigned int i;
+
+               tmpname = temp_file(score, ".licensed", e->file->name);
+               out = fopen(tmpname, "w");
+               if (!out)
+                       err(1, "Opening %s", tmpname);
+               if (fprintf(out, "%s\n", license_desc) < 0)
+                       err(1, "Writing %s", tmpname);
+
+               for (i = 0; e->file->lines[i]; i++)
+                       if (fprintf(out, "%s\n", e->file->lines[i]) < 0)
+                               err(1, "Writing %s", tmpname);
+
+               if (fclose(out) != 0)
+                       err(1, "Closing %s", tmpname);
+
+               if (!move_file(tmpname, e->file->fullname))
+                       err(1, "Moving %s to %s", tmpname, e->file->fullname);
+       }
+}
+
 struct ccanlint license_comment = {
        .key = "license_comment",
        .name = "Source and header files refer to LICENSE",
        .check = check_license_comment,
+       .handle = add_license_comment,
        .needs = "license_exists"
 };
 REGISTER_TEST(license_comment);