+
+static char *extension_table=NULL;
+static int nexts;
+static int max_ext_width;
+
+static int
+extension_cmp(void *a, void *b)
+{
+ return (strlen((char *)a) - strlen((char *)b));
+}
+
+
+//
+// This is the api LaunchServices uses to inform the kernel
+// the list of package extensions to ignore.
+//
+// Internally we keep the list sorted by the length of the
+// the extension (from longest to shortest). We sort the
+// list of extensions so that we can speed up our searches
+// when comparing file names -- we only compare extensions
+// that could possibly fit into the file name, not all of
+// them (i.e. a short 8 character name can't have an 8
+// character extension).
+//
+__private_extern__ int
+set_package_extensions_table(void *data, int nentries, int maxwidth)
+{
+ char *new_exts, *ptr;
+ int error, i, len;
+
+ if (nentries <= 0 || nentries > 1024 || maxwidth <= 0 || maxwidth > 255) {
+ return EINVAL;
+ }
+
+ MALLOC(new_exts, char *, nentries * maxwidth, M_TEMP, M_WAITOK);
+
+ error = copyin(data, new_exts, nentries * maxwidth);
+ if (error) {
+ FREE(new_exts, M_TEMP);
+ return error;
+ }
+
+ if (extension_table) {
+ FREE(extension_table, M_TEMP);
+ }
+ extension_table = new_exts;
+ nexts = nentries;
+ max_ext_width = maxwidth;
+
+ qsort(extension_table, nexts, maxwidth, extension_cmp);
+
+ return 0;
+}
+
+
+static int
+is_package_name(char *name, int len)
+{
+ int i, extlen;
+ char *ptr, *name_ext;
+
+ if (len <= 3) {
+ return 0;
+ }
+
+ name_ext = NULL;
+ for(ptr=name; *ptr != '\0'; ptr++) {
+ if (*ptr == '.') {
+ name_ext = ptr;
+ }
+ }
+
+ // if there is no "." extension, it can't match
+ if (name_ext == NULL) {
+ return 0;
+ }
+
+ // advance over the "."
+ name_ext++;
+
+ // now iterate over all the extensions to see if any match
+ ptr = &extension_table[0];
+ for(i=0; i < nexts; i++, ptr+=max_ext_width) {
+ extlen = strlen(ptr);
+ if (strncmp(name_ext, ptr, extlen) == 0 && name_ext[extlen] == '\0') {
+ // aha, a match!
+ return 1;
+ }
+ }
+
+ // if we get here, no extension matched
+ return 0;
+}
+
+//
+// Determine if a name is "inappropriate" where the definition
+// of "inappropriate" is up to higher level execs. Currently
+// that's limited to /System.
+//
+static int
+is_inappropriate_name(char *name, int len)
+{
+ char *bad_names[] = { "System" };
+ int bad_len[] = { 6 };
+ int i;
+
+ for(i=0; i < sizeof(bad_names) / sizeof(bad_names[0]); i++) {
+ if (len == bad_len[i] && strcmp(name, bad_names[i]) == 0) {
+ return 1;
+ }
+ }
+
+ // if we get here, no name matched
+ return 0;
+}
+
+
+