Example #1
0
static void update_one(const char *path)
{
	if (!verify_path(path)) {
		fprintf(stderr, "Ignoring path %s\n", path);
		return;
	}
	if (mark_valid_only) {
		if (mark_ce_flags(path, CE_VALID, mark_valid_only == MARK_FLAG))
			die("Unable to mark file %s", path);
		return;
	}
	if (mark_skip_worktree_only) {
		if (mark_ce_flags(path, CE_SKIP_WORKTREE, mark_skip_worktree_only == MARK_FLAG))
			die("Unable to mark file %s", path);
		return;
	}

	if (force_remove) {
		if (remove_file_from_cache(path))
			die("git update-index: unable to remove %s", path);
		report("remove '%s'", path);
		return;
	}
	if (process_path(path))
		die("Unable to process path %s", path);
	report("add '%s'", path);
}
Example #2
0
static int add_cacheinfo(unsigned int mode, const struct object_id *oid,
			 const char *path, int stage)
{
	int size, len, option;
	struct cache_entry *ce;

	if (!verify_path(path))
		return error("Invalid path '%s'", path);

	len = strlen(path);
	size = cache_entry_size(len);
	ce = xcalloc(1, size);

	oidcpy(&ce->oid, oid);
	memcpy(ce->name, path, len);
	ce->ce_flags = create_ce_flags(stage);
	ce->ce_namelen = len;
	ce->ce_mode = create_ce_mode(mode);
	if (assume_unchanged)
		ce->ce_flags |= CE_VALID;
	option = allow_add ? ADD_CACHE_OK_TO_ADD : 0;
	option |= allow_replace ? ADD_CACHE_OK_TO_REPLACE : 0;
	if (add_cache_entry(ce, option))
		return error("%s: cannot add to the index - missing --add option?",
			     path);
	report("add '%s'", path);
	return 0;
}
Example #3
0
int main(int argc, char **argv)
{
	int i, newfd, entries;

	entries = read_cache();
	if (entries < 0) {
		perror("cache corrupted");
		return -1;
	}

	newfd = open(".dircache/index.lock", O_RDWR | O_CREAT | O_EXCL, 0600);
	if (newfd < 0) {
		perror("unable to create new cachefile");
		return -1;
	}
	for (i = 1 ; i < argc; i++) {
		char *path = argv[i];
		if (!verify_path(path)) {
			fprintf(stderr, "Ignoring path %s\n", argv[i]);
			continue;
		}
		if (add_file_to_cache(path)) {
			fprintf(stderr, "Unable to add %s to database\n", path);
			goto out;
		}
	}
	if (!write_cache(newfd, active_cache, active_nr) && !rename(".dircache/index.lock", ".dircache/index"))
		return 0;
out:
	unlink(".dircache/index.lock");
}
Example #4
0
/*===========================================================================*
 *				go_down					     *
 *===========================================================================*/
static int go_down(
	char path[PATH_MAX],    /* path to add the name to */
	struct inode *parent,   /* inode of the current directory */
	char *name,             /* name of the directory entry */
	struct inode **res_ino, /* place to store resulting inode */
	struct sffs_attr *attr  /* place to store inode attributes */
)
{
/* Given a directory inode and a name, progress into a directory entry.
 */
  struct inode *ino;
  int r, stale = 0;

  if ((r = push_path(path, name)) != OK)
	return r;

  dprintf(("%s: go_down: name '%s', path now '%s'\n", sffs_name, name, path));

  ino = lookup_dentry(parent, name);

  dprintf(("%s: lookup_dentry('%s') returned %p\n", sffs_name, name, ino));

  if (ino != NULL)
	r = verify_path(path, ino, attr, &stale);
  else
	r = sffs_table->t_getattr(path, attr);

  dprintf(("%s: path query returned %d\n", sffs_name, r));

  if (r != OK) {
	if (ino != NULL) {
		put_inode(ino);

		ino = NULL;
	}

	if (!stale)
		return r;
  }

  dprintf(("%s: name '%s'\n", sffs_name, name));

  if (ino == NULL) {
	if ((ino = get_free_inode()) == NULL)
		return ENFILE;

	dprintf(("%s: inode %p ref %d\n", sffs_name, ino, ino->i_ref));

	ino->i_flags = MODE_TO_DIRFLAG(attr->a_mode);

	add_dentry(parent, name, ino);
  }

  *res_ino = ino;
  return OK;
}
Example #5
0
JournalStore* journal_store_open(JamAccount *acc, gboolean create, GError **err) {
	JournalStore *js = NULL;
	char *path = NULL;
	sqlite3 *db = NULL;
	int ret;
	gboolean exists;

	path = conf_make_account_path(acc, "journal.db");
	exists = g_file_test(path, G_FILE_TEST_EXISTS);

	if (!exists && !create) {
		g_set_error(err, 0, 0, "No offline copy of this journal.");
		goto out;
	}

	if (!verify_path(path, FALSE, &err))
		goto out;

	ret = sqlite3_open(path, &db);
	if (ret != SQLITE_OK) {
		g_set_error(err, 0, 0, "sqlite error %d: %s", ret, sqlite3_errmsg(db));
		goto out;
	}

	sqlite3_trace(db, sql_trace, NULL);

	if (exists) {
		if (!check_version(db)) {
			g_set_error(err, 0, 0,
					"The on-disk journal version differs from "
					"the version understood by this version of LogJam.  "
					"You need to resynchronize your journal.");
			goto out;
		}
	} else {
		if (!init_db(db, err))
			goto out;
	}

	js = g_new0(JournalStore, 1);
	js->account = acc;
	js->db = db;

out:
	g_free(path);
	if (!js && db) sqlite3_close(db);
	return js;
}
Example #6
0
static void update_one(const char *path)
{
	int stat_errno = 0;
	struct stat st;

	if (mark_valid_only || mark_skip_worktree_only || force_remove ||
	    mark_fsmonitor_only)
		st.st_mode = 0;
	else if (lstat(path, &st) < 0) {
		st.st_mode = 0;
		stat_errno = errno;
	} /* else stat is valid */

	if (!verify_path(path, st.st_mode)) {
		fprintf(stderr, "Ignoring path %s\n", path);
		return;
	}
	if (mark_valid_only) {
		if (mark_ce_flags(path, CE_VALID, mark_valid_only == MARK_FLAG))
			die("Unable to mark file %s", path);
		return;
	}
	if (mark_skip_worktree_only) {
		if (mark_ce_flags(path, CE_SKIP_WORKTREE, mark_skip_worktree_only == MARK_FLAG))
			die("Unable to mark file %s", path);
		return;
	}
	if (mark_fsmonitor_only) {
		if (mark_ce_flags(path, CE_FSMONITOR_VALID, mark_fsmonitor_only == MARK_FLAG))
			die("Unable to mark file %s", path);
		return;
	}

	if (force_remove) {
		if (remove_file_from_cache(path))
			die("git update-index: unable to remove %s", path);
		report("remove '%s'", path);
		return;
	}
	if (process_path(path, &st, stat_errno))
		die("Unable to process path %s", path);
	report("add '%s'", path);
}
Example #7
0
int			msh_exec(char **args, t_env *tenv)
{
	char	*path;
	char	**env;
	pid_t	pid;

	if ((path = verify_path(tenv, args)) == NULL)
		return (-1);
	env = tenv_to_star(tenv);
	pid = fork();
	if (pid == 0)
	{
		execve(path, args, env);
		exit(0);
	}
	if (pid > 0)
		waitpid(pid, 0, 0);
	ft_strdel(&path);
	ft_starfree(env);
	return (0);
}
Example #8
0
/*===========================================================================*
 *				verify_inode				     *
 *===========================================================================*/
int verify_inode(
	struct inode *ino,    	/* inode to verify */
	char path[PATH_MAX],  	/* buffer in which to store the path */
	struct sffs_attr *attr	/* buffer for attributes, or NULL */
)
{
/* Given an inode, construct a path identifying the inode, and check whether
 * that path is still valid for that inode (as far as we can tell). As a side
 * effect, store attributes in the given attribute structure if not NULL (its
 * a_mask member must then be set).
 */
  struct sffs_attr attr2;
  int r;

  if ((r = make_path(path, ino)) != OK) return r;

  if (attr == NULL) {
	attr2.a_mask = 0;

	attr = &attr2;
  }

  return verify_path(path, ino, attr, NULL);
}
Example #9
0
static void read_index_info(int line_termination)
{
	struct strbuf buf = STRBUF_INIT;
	struct strbuf uq = STRBUF_INIT;

	while (strbuf_getline(&buf, stdin, line_termination) != EOF) {
		char *ptr, *tab;
		char *path_name;
		unsigned char sha1[20];
		unsigned int mode;
		unsigned long ul;
		int stage;

		/* This reads lines formatted in one of three formats:
		 *
		 * (1) mode         SP sha1          TAB path
		 * The first format is what "git apply --index-info"
		 * reports, and used to reconstruct a partial tree
		 * that is used for phony merge base tree when falling
		 * back on 3-way merge.
		 *
		 * (2) mode SP type SP sha1          TAB path
		 * The second format is to stuff "git ls-tree" output
		 * into the index file.
		 *
		 * (3) mode         SP sha1 SP stage TAB path
		 * This format is to put higher order stages into the
		 * index file and matches "git ls-files --stage" output.
		 */
		errno = 0;
		ul = strtoul(buf.buf, &ptr, 8);
		if (ptr == buf.buf || *ptr != ' '
		    || errno || (unsigned int) ul != ul)
			goto bad_line;
		mode = ul;

		tab = strchr(ptr, '\t');
		if (!tab || tab - ptr < 41)
			goto bad_line;

		if (tab[-2] == ' ' && '0' <= tab[-1] && tab[-1] <= '3') {
			stage = tab[-1] - '0';
			ptr = tab + 1; /* point at the head of path */
			tab = tab - 2; /* point at tail of sha1 */
		}
		else {
			stage = 0;
			ptr = tab + 1; /* point at the head of path */
		}

		if (get_sha1_hex(tab - 40, sha1) || tab[-41] != ' ')
			goto bad_line;

		path_name = ptr;
		if (line_termination && path_name[0] == '"') {
			strbuf_reset(&uq);
			if (unquote_c_style(&uq, path_name, NULL)) {
				die("git update-index: bad quoting of path name");
			}
			path_name = uq.buf;
		}

		if (!verify_path(path_name)) {
			fprintf(stderr, "Ignoring path %s\n", path_name);
			continue;
		}

		if (!mode) {
			/* mode == 0 means there is no such path -- remove */
			if (remove_file_from_cache(path_name))
				die("git update-index: unable to remove %s",
				    ptr);
		}
		else {
			/* mode ' ' sha1 '\t' name
			 * ptr[-1] points at tab,
			 * ptr[-41] is at the beginning of sha1
			 */
			ptr[-42] = ptr[-1] = 0;
			if (add_cacheinfo(mode, sha1, path_name, stage))
				die("git update-index: unable to update %s",
				    path_name);
		}
		continue;

	bad_line:
		die("malformed index info %s", buf.buf);
	}
	strbuf_release(&buf);
	strbuf_release(&uq);
}
Example #10
0
static GString *append_listing(GString *object, const char *name,
				gboolean pcsuite, size_t *size, int *err)
{
	struct stat fstat, dstat;
	struct dirent *ep;
	DIR *dp;
	gboolean root;
	int ret;

	root = g_str_equal(name, obex_option_root_folder());

	dp = opendir(name);
	if (dp == NULL) {
		if (err)
			*err = -ENOENT;
		goto failed;
	}

	if (root)
		object = g_string_append(object, FL_PARENT_FOLDER_ELEMENT);

	ret = verify_path(name);
	if (ret < 0) {
		*err = ret;
		goto failed;
	}

	ret = stat(name, &dstat);

	if (ret < 0) {
		if (err)
			*err = -errno;
		goto failed;
	}

	while ((ep = readdir(dp))) {
		char *filename;
		char *fullname;
		char *line;

		if (ep->d_name[0] == '.')
			continue;

		filename = g_filename_to_utf8(ep->d_name, -1, NULL, NULL, NULL);
		if (name == NULL) {
			error("g_filename_to_utf8: invalid filename");
			continue;
		}

		fullname = g_build_filename(name, ep->d_name, NULL);

		ret = stat(fullname, &fstat);

		if (ret < 0) {
			DBG("stat: %s(%d)", strerror(errno), errno);
			g_free(filename);
			g_free(fullname);
			continue;
		}

		g_free(fullname);

		line = file_stat_line(filename, &fstat, &dstat, root, FALSE);
		if (line == NULL) {
			g_free(filename);
			continue;
		}

		g_free(filename);

		object = g_string_append(object, line);
		g_free(line);
	}

	closedir(dp);

	object = g_string_append(object, FL_BODY_END);
	if (size)
		*size = object->len;

	if (err)
		*err = 0;

	return object;

failed:
	if (dp)
		closedir(dp);

	g_string_free(object, TRUE);
	return NULL;
}
char *qdb_read(qdb_handle_t h, char *path, unsigned int *value_len) {
    struct qdb_hdr hdr;
    char *value;
    uint32_t got_data;
    rw_ret_t ret;

    if (!h)
        return NULL;
    if (!verify_path(path))
        return NULL;

    hdr.type = QDB_CMD_READ;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = 0;
    if (!send_command_to_daemon(h, &hdr, NULL))
        /* some fatal error perhaps? */
        return NULL;
    if (!get_response(h, &hdr))
        return NULL;
    /* TODO: make this distinguishable from other errors */
    if (hdr.type == QDB_RESP_ERROR_NOENT) {
        errno = ENOENT;
        return NULL;
    }
    if (hdr.type == QDB_RESP_ERROR) {
        /* TODO? */
        assert(hdr.data_len == 0);
        return NULL;
    }
    assert(hdr.type == QDB_RESP_READ);
    /* +1 for terminating \0 */
    value = malloc(hdr.data_len+1);
    if (!value)
        return NULL;
    got_data = 0;
    while (got_data < hdr.data_len) {
#ifdef WIN32
        ret = hdr.data_len - got_data; // this function always reads the requested size
        if (!QioReadBuffer(h->read_pipe, value+got_data, hdr.data_len-got_data)) {
#else
        ret = read(h->fd, value+got_data, hdr.data_len-got_data);
        if (ret <= 0) {
#endif
            free(value);
            return NULL;
        }
        got_data += ret;
    }
    value[got_data] = '\0';

    if (value_len)
        *value_len = got_data;

    return value;
}

char **qdb_list(qdb_handle_t h, char *path, unsigned int *list_len) {
    struct qdb_hdr hdr;
    struct path_list *plist = NULL;
    struct path_list *plist_tmp;
    int count = 0;
    char **ret;

    if (!h)
        return NULL;
    if (!verify_path(path))
        return NULL;

    hdr.type = QDB_CMD_LIST;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = 0;
    if (!send_command_to_daemon(h, &hdr, NULL))
        /* some fatal error perhaps? */
        return NULL;

    /* receive entries (QDB_RESP_LIST messages) and add them to plist at the
     * beginning. This means that list will be in reverse order. */
    while (1) {
        if (!get_response(h, &hdr)) {
            free_path_list(plist);
            return NULL;
        }
        /* TODO: QDB_RESP_ERROR ? (current daemon do not send such response to
         * list */
        assert(hdr.type == QDB_RESP_LIST);
        if (!hdr.path[0])
            /* end of list */
            break;

        plist_tmp = malloc(sizeof(*plist_tmp));
        if (!plist_tmp) {
            /* OOM */
            free_path_list(plist);
            return NULL;
        }

        plist_tmp->path = strdup(hdr.path);
        if (!plist_tmp->path) {
            /* OOM */
            free_path_list(plist);
            return NULL;
        }
        plist_tmp->next = plist;
        plist = plist_tmp;
        count++;
    }
    ret = malloc((count+1) * sizeof(char*));
    if (!ret) {
        /* OOM */
        free_path_list(plist);
        return NULL;
    }

    /* End of table marker */
    ret[count] = NULL;

    if (list_len)
        *list_len = count;

    /* write responses to array, in reverse order so entries will be back
     * sorted */
    while (plist && count) {
        ret[--count] = plist->path;
        plist_tmp = plist;
        plist = plist->next;
        free(plist_tmp);
    }
    return ret;
}

char **qdb_multiread(qdb_handle_t h, char *path,
        unsigned int **values_len, unsigned int *list_len) {
    struct qdb_hdr hdr;
    int count = 0;
    char *value;
    uint32_t got_data;
    char **ret = NULL, **ret2;
    rw_ret_t read_ret;
    unsigned int *len_ret = NULL, *len_ret2;

    if (!h)
        return NULL;
    if (!verify_path(path))
        return NULL;

    hdr.type = QDB_CMD_MULTIREAD;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = 0;
    if (!send_command_to_daemon(h, &hdr, NULL))
        /* some fatal error perhaps? */
        return NULL;

    /* initial arrays */
    ret = malloc(2*sizeof(char*));
    if (!ret) {
        return NULL;
    }

    if (values_len) {
        len_ret = malloc(sizeof(unsigned int));
        if (!len_ret) {
            free(ret);
            return NULL;
        }
    }

    /* receive entries (QDB_RESP_MULTIREAD messages) */
    while (1) {
        if (!get_response(h, &hdr)) {
            free(ret);
            free(len_ret);
            return NULL;
        }
        assert(hdr.type == QDB_RESP_MULTIREAD);
        if (!hdr.path[0])
            /* end of list */
            break;

        /* +1 for terminating \0 */
        value = malloc(hdr.data_len+1);
        if (!value) {
            free(ret);
            free(len_ret);
            return NULL;
        }
        got_data = 0;
        while (got_data < hdr.data_len) {
#ifdef WIN32
            read_ret = hdr.data_len - got_data; // this function always reads the requested size
            if (!QioReadBuffer(h->read_pipe, value+got_data, hdr.data_len-got_data)) {
#else
            read_ret = read(h->fd, value+got_data, hdr.data_len-got_data);
            if (read_ret <= 0) {
#endif
                free(value);
                free(ret);
                free(len_ret);
                return NULL;
            }
            got_data += read_ret;
        }
        value[got_data] = '\0';

        /* (path+value)*count + NULL,NULL
         * Note that count is still unchanged */
        ret2 = realloc(ret, 2*(count+2)*sizeof(char*));
        if (!ret2) {
            free(ret);
            free(value);
            free(len_ret);
            return NULL;
        }
        ret = ret2;

        if (values_len) {
            len_ret2 = realloc(len_ret, (count+2)*sizeof(unsigned int));
            if (!len_ret2) {
                free(len_ret);
                free(value);
                free(ret);
                return NULL;
            }
            len_ret = len_ret2;
        }

        /* first path */
        ret[2*count] = strdup(hdr.path);
        /* then data */
        ret[2*count+1] = value;
        /* and data len if requested */
        if (values_len)
            len_ret[count] = hdr.data_len;
        count++;
    }

    /* End of table marker */
    ret[2*count] = NULL;
    ret[2*count+1] = NULL;

    if (values_len)
        *values_len = len_ret;
    if (list_len)
        *list_len = count;

    return ret;
}

/** Write single value to QubesDB, will override existing entry.
 */
int qdb_write(qdb_handle_t h, char *path, char *value, unsigned int value_len) {
    struct qdb_hdr hdr;

    if (!h)
        return 0;
    /* daemon will verify data anyway, but check here to return meaningful
     * error message */
    if (!verify_path(path))
        return 0;
    if (!value || value_len > QDB_MAX_DATA)
        return 0;

    hdr.type = QDB_CMD_WRITE;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = value_len;
    if (!send_command_to_daemon(h, &hdr, value))
        /* some fatal error perhaps? */
        return 0;
    if (!get_response(h, &hdr))
        return 0;
    if (hdr.type == QDB_RESP_ERROR) {
        /* TODO? */
        assert(hdr.data_len == 0);
        return 0;
    }
    assert(hdr.type == QDB_RESP_OK);
    assert(hdr.data_len == 0);
    return 1;
}

/** Common function for simple commands - only path as argument and no return data.
 * @param h Connection handle
 * @param path Entry path
 * @param cmd Command (hdr.type content)
 * @return 1 on success, 0 on failure
 */
static int qdb__simple_cmd(qdb_handle_t h, char *path, int cmd) {
    struct qdb_hdr hdr;

    if (!h)
        return 0;
    if (!verify_path(path))
        return 0;

    hdr.type = cmd;
    /* already verified string length */
#ifdef WIN32
    StringCbCopyA(hdr.path, sizeof(hdr.path), path);
#else
    strcpy(hdr.path, path);
#endif
    hdr.data_len = 0;

    if (!send_command_to_daemon(h, &hdr, NULL))
        /* some fatal error perhaps? */
        return 0;

    if (!get_response(h, &hdr))
        return 0;
    /* TODO: ignore NOENT for now */
    if (hdr.type == QDB_RESP_ERROR_NOENT) {
        return 1;
    }
    if (hdr.type == QDB_RESP_ERROR) {
        /* TODO? */
        assert(hdr.data_len == 0);
        return 0;
    }
    assert(hdr.type == QDB_RESP_OK);
    assert(hdr.data_len == 0);
    return 1;
}

int qdb_watch(qdb_handle_t h, char *path) {
    return qdb__simple_cmd(h, path, QDB_CMD_WATCH);
}

int qdb_unwatch(qdb_handle_t h, char *path) {
    return qdb__simple_cmd(h, path, QDB_CMD_UNWATCH);
}

int qdb_rm(qdb_handle_t h, char *path) {
    return qdb__simple_cmd(h, path, QDB_CMD_RM);
}

#ifdef WIN32
HANDLE
#else
int
#endif
qdb_watch_fd(qdb_handle_t h) {
#ifdef WIN32
    /* TODO: begin overlapped read operation and return event handle */
    /* TODO: for overlapped read, pipe should be opened in overlapped mode */
    return INVALID_HANDLE_VALUE;
#else
    if (!h->connected) {
        if (!connect_to_daemon(h)) {
            /* reconnect failed */
            errno = EPIPE;
            return -1;
        }
        /* FIXME: register watches again */
    }
    return h->fd;
#endif
}

char *qdb_read_watch(qdb_handle_t h) {
    struct qdb_hdr hdr;
    struct path_list *w;
    char *ret = NULL;
    int len;

    if (!h)
        return 0;

    /** already received event */
    if (h->watch_list) {
        w = h->watch_list;
        h->watch_list = w->next;
        ret = w->path;
        free(w);
    } else {
#ifdef WIN32
        len = sizeof(hdr);
        if (!QioReadBuffer(h->read_pipe, &hdr, sizeof(hdr))) {
#else
        if ((len=read(h->fd, &hdr, sizeof(hdr))) < sizeof(hdr)) {
#endif
            if (len==0)
                errno = EPIPE;
            return NULL;
        }
        /* only MULTIREAD is handled with multiple qdb_* calls, so if this
         * isn't WATCH we missed something */
        assert(hdr.type == QDB_RESP_WATCH);
        ret = strdup(hdr.path);
    }
    return ret;
}

#ifdef WIN32
void qdb_free(void *p) {
    free(p);
}
Example #12
0
DataHandler::resource DataHandler::read_resource(std::string path, std::string cookies, DataHandler::resource * data) {
    // prepend cwd() to path

    if (!verify_path(path))
        path = "/index.html";

    std::string cwd = get_working_path();
    path = cwd + path;
    this->logger->debug("Checking resource at: " + path);

    // first check if such a file even exists
    int fd = open(path.c_str(), O_RDONLY);
    if (fd < 0) {
        char * err = std::strerror(errno);
        throw DataHandler::FileNotFound("Error while reading file contents at " + path + ": " + std::string(err ? err : "unknown error"));
    }
    close(fd);

    // check mime type of resource
    DataHandler::Exec runner;
    std::string args[2] = { "/usr/bin/file", path };
    DataHandler::resource file_mime = runner.run_command(args);
    char * mime = file_mime.data;
    std::string ext = path.substr(path.length()-3);
    for(char c : ext)
        c = std::toupper(c);

    DataHandler::resource output;
    // now check for known mime types
    if (is(mime, "executable")) {
        // run the script, pass the data
        std::string args[2] = { path, "" }; // TODO: Fix me too!
        DataHandler::resource script_output = runner.run_command(args, data, cookies);
        output.data = script_output.data;
        output.size = script_output.size;
        output.type = "executable";
    }
    // TODO: Move this definition to some more reasonable place
    else if (is(mime, "HTML"))                       { output.type = "text/html; charset=UTF-8";  }
    else if (is(mime, "ASCII") && ext == "CSS")      { output.type = "text/css";                  }
    else if (is(mime, "ERROR") || is(mime, "ASCII")) { output.type = "text/plain; charset=UTF-8"; }
    else if (is(mime, "JPEG"))                       { output.type = "image/jpeg";                }
    else if (is(mime, "PNG"))                        { output.type = "image/png";                 }
    else if (is(mime, "MS Windows icon"))            { output.type = "image/vnd.microsoft.icon";  }

    if (output.type.length() > 0 && output.type != "executable") {
        DataHandler::Static getter;
        DataHandler::resource f = getter.get_file(path);
        output.data = f.data;
        output.size = f.size;
    }
    else if (output.type.length() == 0){
        std::string error_str = "Unsupported mime type: " + std::string(mime);
        // drop 'local' part of path
        size_t pos = 0;
        while ((pos = error_str.find(cwd)) != std::string::npos )
            error_str.erase(pos, cwd.length());

        throw DataHandler::Unsupported(error_str);
    }

    return output;
}