<commit_before>#include <sys/types.h>
#include <sys/stat.h>

#include <assert.h>
#include <ctype.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>

#include "pkg.h"
#include "pkg_event.h"
#include "pkg_private.h"


struct hardlinks {
	ino_t *inodes;
	size_t len;
	size_t cap;
};

int
ports_parse_plist(struct pkg *pkg, char *plist)
{
	bool ignore_next = false;
	char *plist_p, *buf, *p, *plist_buf;
	char comment[2];
	int nbel, i;
	size_t next;
	size_t len;
	size_t j;
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];
	char path[MAXPATHLEN + 1];
	char *last_plist_file = NULL;
	char *cmd = NULL;
	const char *prefix = NULL;
	struct stat st;
	int ret = EPKG_OK;
	off_t sz = 0;
	const char *slash;
	int64_t flatsize = 0;
	struct hardlinks hardlinks = {NULL, 0, 0};
	bool regular;
	struct sbuf *exec_scripts = sbuf_new_auto();
	struct sbuf *unexec_scripts = sbuf_new_auto();
	struct sbuf *pre_unexec_scripts = sbuf_new_auto();
	struct sbuf *post_unexec_scripts = sbuf_new_auto();
	void *set = NULL;
	const char *uname = NULL;
	const char *gname = NULL;
	mode_t perm=0;
	regex_t preg1, preg2;
	regmatch_t pmatch[2];

	regcomp(&preg1, "[[:space:]]\"(/[^\"]+)", REG_EXTENDED);
	regcomp(&preg2, "[[:space:]](/[[:graph:]/]+)", REG_EXTENDED);

	buf = NULL;
	p = NULL;

	assert(pkg != NULL);
	assert(plist != NULL);

	if ((ret = file_to_buffer(plist, &plist_buf, &sz)) != EPKG_OK)
		return (ret);

	pkg_get(pkg, PKG_PREFIX, &prefix);
	slash = prefix[strlen(prefix) - 1] == '/' ? "" : "/";

	nbel = split_chr(plist_buf, '\n');

	next = strlen(plist_buf);
	plist_p = plist_buf;

	for (i = 0; i <= nbel; i++) {
		if (ignore_next)
			continue;

		if (plist_p[0] == '@') {
			if (STARTS_WITH(plist_p, "@cwd")) {
				buf = plist_p;
				buf += 4;
				while (isspace(buf[0]))
					buf++;
				/* with no arguments default to the original
				 * prefix */
				if (buf[0] == '\0')
					pkg_get(pkg, PKG_PREFIX, &prefix);
				else
					prefix = buf;
				slash = prefix[strlen(prefix) - 1] == '/' ? "" : "/";
			} else if (STARTS_WITH(plist_p, "@ignore")) {
				/* ignore the next line */
				ignore_next = true;
			} else if (STARTS_WITH(plist_p, "@comment ")) {
				/* DO NOTHING: ignore the comments */
			} else if (STARTS_WITH(plist_p, "@unexec ") ||
					   STARTS_WITH(plist_p, "@exec ")) {
				buf = plist_p;

				while (!isspace(buf[0]))
					buf++;

				while (isspace(buf[0]))
					buf++;

				if (format_exec_cmd(&cmd, buf, prefix, last_plist_file) != EPKG_OK)
					continue;

				if (plist_p[1] == 'u') {
					comment[0] = '\0';
					/* workaround to detect the @dirrmtry */
					if (STARTS_WITH(cmd, "rmdir ")) {
						comment[0] = '#';
						comment[1] = '\0';
					} else if (STARTS_WITH(cmd, "/bin/rmdir ")) {
						comment[0] = '#';
						comment[1] = '\0';
					}
					/* remove the glob if any */
					if (comment[0] == '#') {
						if (strchr(cmd, '*'))
						comment[0] = '\0';

						buf = cmd;

						/* start remove mkdir -? */
						/* remove the command */
						while (!isspace(buf[0]))
							buf++;

						while (isspace(buf[0]))
							buf++;

						if (buf[0] == '-')
							comment[0] = '\0';
						/* end remove mkdir -? */
					}

					sbuf_printf(unexec_scripts, "%s%s\n",comment, cmd);

					/* workaround to detect the @dirrmtry */
					if (comment[0] == '#') {
						buf = cmd;

						/* remove the @dirrm{,try}
						 * command */
						while (!isspace(buf[0]))
							buf++;

						split_chr(buf, '|');

						if (strstr(buf, "\"/")) {
							while (regexec(&preg1, buf, 2, pmatch, 0) == 0) {
								strlcpy(path, &buf[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so + 1);
								buf+=pmatch[1].rm_eo;
								if (!strcmp(path, "/dev/null"))
									continue;
								ret += pkg_adddir_attr(pkg, path, uname, gname, perm, 1);
							}
						} else {
							while (regexec(&preg2, buf, 2, pmatch, 0) == 0) {
								strlcpy(path, &buf[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so + 1);
								buf+=pmatch[1].rm_eo;
								if (!strcmp(path, "/dev/null"))
									continue;
								ret += pkg_adddir_attr(pkg, path, uname, gname, perm, 1);
							}
						}

					}
				} else {
					if (sbuf_len(exec_scripts) == 0)
						sbuf_cat(exec_scripts, "#@exec\n"); /* to be able to regenerate the @exec in pkg2legacy */
					sbuf_printf(exec_scripts, "%s\n", cmd);
				}

				free(cmd);

			} else if (STARTS_WITH(plist_p, "@dirrm ") || STARTS_WITH(plist_p, "@dirrmtry ")) {

				buf = plist_p;

				/* remove the @dirrm or @dirrmtry */
				while (!isspace(buf[0]))
					buf++;

				while (isspace(buf[0]))<commit_msg>Just check @dirrm (@dirrmtry will automatically match, this also matches @dirrm\t and fixes gtkhx port<commit_after>#include <sys/types.h>
#include <sys/stat.h>

#include <assert.h>
#include <ctype.h>
#include <regex.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
#include <unistd.h>

#include "pkg.h"
#include "pkg_event.h"
#include "pkg_private.h"


struct hardlinks {
	ino_t *inodes;
	size_t len;
	size_t cap;
};

int
ports_parse_plist(struct pkg *pkg, char *plist)
{
	bool ignore_next = false;
	char *plist_p, *buf, *p, *plist_buf;
	char comment[2];
	int nbel, i;
	size_t next;
	size_t len;
	size_t j;
	char sha256[SHA256_DIGEST_LENGTH * 2 + 1];
	char path[MAXPATHLEN + 1];
	char *last_plist_file = NULL;
	char *cmd = NULL;
	const char *prefix = NULL;
	struct stat st;
	int ret = EPKG_OK;
	off_t sz = 0;
	const char *slash;
	int64_t flatsize = 0;
	struct hardlinks hardlinks = {NULL, 0, 0};
	bool regular;
	struct sbuf *exec_scripts = sbuf_new_auto();
	struct sbuf *unexec_scripts = sbuf_new_auto();
	struct sbuf *pre_unexec_scripts = sbuf_new_auto();
	struct sbuf *post_unexec_scripts = sbuf_new_auto();
	void *set = NULL;
	const char *uname = NULL;
	const char *gname = NULL;
	mode_t perm=0;
	regex_t preg1, preg2;
	regmatch_t pmatch[2];

	regcomp(&preg1, "[[:space:]]\"(/[^\"]+)", REG_EXTENDED);
	regcomp(&preg2, "[[:space:]](/[[:graph:]/]+)", REG_EXTENDED);

	buf = NULL;
	p = NULL;

	assert(pkg != NULL);
	assert(plist != NULL);

	if ((ret = file_to_buffer(plist, &plist_buf, &sz)) != EPKG_OK)
		return (ret);

	pkg_get(pkg, PKG_PREFIX, &prefix);
	slash = prefix[strlen(prefix) - 1] == '/' ? "" : "/";

	nbel = split_chr(plist_buf, '\n');

	next = strlen(plist_buf);
	plist_p = plist_buf;

	for (i = 0; i <= nbel; i++) {
		if (ignore_next)
			continue;

		if (plist_p[0] == '@') {
			if (STARTS_WITH(plist_p, "@cwd")) {
				buf = plist_p;
				buf += 4;
				while (isspace(buf[0]))
					buf++;
				/* with no arguments default to the original
				 * prefix */
				if (buf[0] == '\0')
					pkg_get(pkg, PKG_PREFIX, &prefix);
				else
					prefix = buf;
				slash = prefix[strlen(prefix) - 1] == '/' ? "" : "/";
			} else if (STARTS_WITH(plist_p, "@ignore")) {
				/* ignore the next line */
				ignore_next = true;
			} else if (STARTS_WITH(plist_p, "@comment ")) {
				/* DO NOTHING: ignore the comments */
			} else if (STARTS_WITH(plist_p, "@unexec ") ||
					   STARTS_WITH(plist_p, "@exec ")) {
				buf = plist_p;

				while (!isspace(buf[0]))
					buf++;

				while (isspace(buf[0]))
					buf++;

				if (format_exec_cmd(&cmd, buf, prefix, last_plist_file) != EPKG_OK)
					continue;

				if (plist_p[1] == 'u') {
					comment[0] = '\0';
					/* workaround to detect the @dirrmtry */
					if (STARTS_WITH(cmd, "rmdir ")) {
						comment[0] = '#';
						comment[1] = '\0';
					} else if (STARTS_WITH(cmd, "/bin/rmdir ")) {
						comment[0] = '#';
						comment[1] = '\0';
					}
					/* remove the glob if any */
					if (comment[0] == '#') {
						if (strchr(cmd, '*'))
						comment[0] = '\0';

						buf = cmd;

						/* start remove mkdir -? */
						/* remove the command */
						while (!isspace(buf[0]))
							buf++;

						while (isspace(buf[0]))
							buf++;

						if (buf[0] == '-')
							comment[0] = '\0';
						/* end remove mkdir -? */
					}

					sbuf_printf(unexec_scripts, "%s%s\n",comment, cmd);

					/* workaround to detect the @dirrmtry */
					if (comment[0] == '#') {
						buf = cmd;

						/* remove the @dirrm{,try}
						 * command */
						while (!isspace(buf[0]))
							buf++;

						split_chr(buf, '|');

						if (strstr(buf, "\"/")) {
							while (regexec(&preg1, buf, 2, pmatch, 0) == 0) {
								strlcpy(path, &buf[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so + 1);
								buf+=pmatch[1].rm_eo;
								if (!strcmp(path, "/dev/null"))
									continue;
								ret += pkg_adddir_attr(pkg, path, uname, gname, perm, 1);
							}
						} else {
							while (regexec(&preg2, buf, 2, pmatch, 0) == 0) {
								strlcpy(path, &buf[pmatch[1].rm_so], pmatch[1].rm_eo - pmatch[1].rm_so + 1);
								buf+=pmatch[1].rm_eo;
								if (!strcmp(path, "/dev/null"))
									continue;
								ret += pkg_adddir_attr(pkg, path, uname, gname, perm, 1);
							}
						}

					}
				} else {
					if (sbuf_len(exec_scripts) == 0)
						sbuf_cat(exec_scripts, "#@exec\n"); /* to be able to regenerate the @exec in pkg2legacy */
					sbuf_printf(exec_scripts, "%s\n", cmd);
				}

				free(cmd);

			} else if (STARTS_WITH(plist_p, "@dirrm")) {
				/* dirrm or dirrmtry */

				buf = plist_p;

				/* remove the @dirrm or @dirrmtry */
				while (!isspace(buf[0]))
					buf++;

				while (isspace(buf[0]))
{'fraction_non_alphanumeric': 0.18541621854162185, 'fraction_numerical': 0.016132501613250163, 'mean_word_length': 2.755654281098546, 'pattern_counts': {'":': 0, '<': 25, '<?xml version=': 0, '>': 23, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3348479', 'n_tokens_mistral': 4626, 'n_tokens_neox': 3657, 'n_words': 838}