Ejemplo n.º 1
0
Archivo: daemon.c Proyecto: Pistos/git
static int run_service(struct interp *itable, struct daemon_service *service)
{
	const char *path;
	int enabled = service->enabled;

	loginfo("Request %s for '%s'",
		service->name,
		itable[INTERP_SLOT_DIR].value);

	if (!enabled && !service->overridable) {
		logerror("'%s': service not enabled.", service->name);
		errno = EACCES;
		return -1;
	}

	if (!(path = path_ok(itable)))
		return -1;

	/*
	 * Security on the cheap.
	 *
	 * We want a readable HEAD, usable "objects" directory, and
	 * a "git-daemon-export-ok" flag that says that the other side
	 * is ok with us doing this.
	 *
	 * path_ok() uses enter_repo() and does whitelist checking.
	 * We only need to make sure the repository is exported.
	 */

	if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
		logerror("'%s': repository not exported.", path);
		errno = EACCES;
		return -1;
	}

	if (service->overridable) {
		service_looking_at = service;
		service_enabled = -1;
		git_config(git_daemon_config, NULL);
		if (0 <= service_enabled)
			enabled = service_enabled;
	}
	if (!enabled) {
		logerror("'%s': service not enabled for '%s'",
			 service->name, path);
		errno = EACCES;
		return -1;
	}

	/*
	 * We'll ignore SIGTERM from now on, we have a
	 * good client.
	 */
	signal(SIGTERM, SIG_IGN);

	return service->fn();
}
Ejemplo n.º 2
0
Archivo: redir.c Proyecto: lb1a/avfs
asmlinkage int virt_getcwd(char *buf, unsigned long size)
{
	int ret;
	char *cwd;
	unsigned long cwdlen;
	char *page;
	char *newcwd;
	unsigned long newlen;
	
	ret = (*orig_getcwd)(buf, size);

	if(!cwd_virtual() || ret < 0)
		return ret;
		
	if(!path_ok(current->fs->pwd))
		return -ENOENT;
	
	page = (char *) __get_free_page(GFP_USER);
	if(!page)
		return -ENOMEM;
	
	cwd = path_pwd(page);
	cwdlen = PAGE_SIZE + (page - cwd) - 1;
	
	if(cwdlen >= OVERLAY_DIR_LEN && 
	   strncmp(cwd, OVERLAY_DIR, OVERLAY_DIR_LEN) == 0) {
		if(cwdlen == OVERLAY_DIR_LEN) {
			newcwd = "/";
			newlen = 1;
		}
		else {
			newcwd = cwd + OVERLAY_DIR_LEN;
			newlen = cwdlen - OVERLAY_DIR_LEN;
		}

		ret = -ERANGE;
		if(newlen + 1 <= size) {
			ret = newlen + 1;
			if(copy_to_user(buf, newcwd, newlen + 1))
				ret = -EFAULT;
		}
	}
	free_page((unsigned long) page);

	return ret;
}
Ejemplo n.º 3
0
Archivo: redir.c Proyecto: lb1a/avfs
static char *get_abs_path(const char *filename)
{
	char *cwd;
	int cwdlen, fnamelen;
	char *abspath, *s;
	char *page;

	if(!path_ok(current->fs->pwd))
		return NULL;

	page = (char *) __get_free_page(GFP_USER);
	if(!page)
		return NULL;

	cwd = path_pwd(page);
	cwdlen = (unsigned int) page + PAGE_SIZE - (unsigned int) cwd - 1;
	if(cwd_virtual() && cwdlen > OVERLAY_DIR_LEN) {
		cwd += OVERLAY_DIR_LEN;
		cwdlen -= OVERLAY_DIR_LEN;
	}
		

	fnamelen = strlen(filename);

	abspath = kmalloc(cwdlen + 1 + fnamelen + 1, GFP_USER);
	if(abspath) {
		s = abspath;
		strncpy(s, cwd, cwdlen);
		s += cwdlen;
		*s++ = '/';
		strncpy(s, filename, fnamelen + 1);
	}
	free_page((unsigned long) page);
	
	return abspath;
}
Ejemplo n.º 4
0
static bool
check_path(const char *path, VALUE *out, int *type)
{
    char *p = strrchr(path, '.');
    if (p != NULL) {
	// The given path already contains a file extension. Let's check if
	// it's a valid one, then try to validate the path.
	int t = 0;
	if (strcmp(p + 1, "rb") == 0) {
	    t = TYPE_RB;
	}
	else if (rbo_enabled && strcmp(p + 1, "rbo") == 0) {
	    t = TYPE_RBO;
	}
	else if (strcmp(p + 1, "bundle") == 0) {
	    t = TYPE_BUNDLE;
	}
	else if (strcmp(p + 1, "so") == 0) {
	    const char *ext = "bundle";
	    const long ext_len = strlen(ext);
	    const long len = p - path;
	    if (len + ext_len + 1 < PATH_MAX) {
		char buf[PATH_MAX];
		strncpy(buf, path, PATH_MAX);
		strcpy(buf + len + 1, ext);
		buf[PATH_MAX - 1] = '\0';
		if (path_ok(buf, out)) {
		    *type = TYPE_BUNDLE;
		    return true;
		}
	    }
	}
	if (t != 0 && path_ok(path, out)) {
	    *type = t;
	    return true;
	}
    }

    // No valid extension, let's append the valid ones and try to validate
    // the path.
    char buf[PATH_MAX];
    if (rbo_enabled) {
	snprintf(buf, sizeof buf, "%s.rbo", path);
	if (path_ok(buf, out)) {
	    *type = TYPE_RBO;
	    return true;
	}
    }
    snprintf(buf, sizeof buf, "%s.rb", path);
    if (path_ok(buf, out)) {
	*type = TYPE_RB;
	return true;
    }
    snprintf(buf, sizeof buf, "%s.bundle", path);
    if (path_ok(buf, out)) {
	*type = TYPE_BUNDLE;
	return true;
    }

    return false;
}
Ejemplo n.º 5
0
static int run_service(char *dir, struct daemon_service *service)
{
	const char *path;
	int enabled = service->enabled;

	loginfo("Request %s for '%s'", service->name, dir);

	if (!enabled && !service->overridable) {
		logerror("'%s': service not enabled.", service->name);
		errno = EACCES;
		return daemon_error(dir, "service not enabled");
	}

	if (!(path = path_ok(dir)))
		return daemon_error(dir, "no such repository");

	/*
	 * Security on the cheap.
	 *
	 * We want a readable HEAD, usable "objects" directory, and
	 * a "git-daemon-export-ok" flag that says that the other side
	 * is ok with us doing this.
	 *
	 * path_ok() uses enter_repo() and does whitelist checking.
	 * We only need to make sure the repository is exported.
	 */

	if (!export_all_trees && access("git-daemon-export-ok", F_OK)) {
		logerror("'%s': repository not exported.", path);
		errno = EACCES;
		return daemon_error(dir, "repository not exported");
	}

	if (service->overridable) {
		service_looking_at = service;
		service_enabled = -1;
		git_config(git_daemon_config, NULL);
		if (0 <= service_enabled)
			enabled = service_enabled;
	}
	if (!enabled) {
		logerror("'%s': service not enabled for '%s'",
			 service->name, path);
		errno = EACCES;
		return daemon_error(dir, "service not enabled");
	}

	/*
	 * Optionally, a hook can choose to deny access to the
	 * repository depending on the phase of the moon.
	 */
	if (access_hook && run_access_hook(service, dir, path))
		return -1;

	/*
	 * We'll ignore SIGTERM from now on, we have a
	 * good client.
	 */
	signal(SIGTERM, SIG_IGN);

	return service->fn();
}
Ejemplo n.º 6
0
static void
cache_cleaner_thread(void *none)
{
    /* Find where it all happens */
    char covers_path[PATH_MAX];
    if (make_cache_root_path(covers_path, PATH_MAX-10)) {
        return;
    }
    strcat(covers_path, "covers");
    const size_t covers_path_length = strlen(covers_path);

    deadbeef->mutex_lock(thread_mutex);
    while (!terminate) {
        time_t oldest_mtime = time(NULL);

        /* Loop through the artist directories */
        DIR *covers_dir = opendir(covers_path);
        struct dirent *covers_subdir;
        while (!terminate && covers_dir && (covers_subdir = readdir(covers_dir))) {
            const int32_t cache_secs = cache_expiry_seconds;
            deadbeef->mutex_unlock(thread_mutex);
            if (cache_secs > 0 && path_ok(covers_path_length, covers_subdir->d_name)) {
                trace("Analyse %s for expired files\n", covers_subdir->d_name);
                const time_t cache_expiry = time(NULL) - cache_secs;

                /* Loop through the image files in this artist directory */
                char subdir_path[PATH_MAX];
                sprintf(subdir_path, "%s/%s", covers_path, covers_subdir->d_name);
                const size_t subdir_path_length = strlen(subdir_path);
                DIR *subdir = opendir(subdir_path);
                struct dirent *entry;
                while (subdir && (entry = readdir(subdir))) {
                    if (path_ok(subdir_path_length, entry->d_name)) {
                        char entry_path[PATH_MAX];
                        sprintf(entry_path, "%s/%s", subdir_path, entry->d_name);

                        /* Test against the cache expiry time (cache invalidation resets are not handled here) */
                        struct stat stat_buf;
                        if (!stat(entry_path, &stat_buf)) {
                            if (stat_buf.st_mtime <= cache_expiry) {
                                trace("%s expired from cache\n", entry_path);
                                remove_cache_item(entry_path, subdir_path, covers_subdir->d_name, entry->d_name);
                            }
                            else if (stat_buf.st_mtime < oldest_mtime) {
                                oldest_mtime = stat_buf.st_mtime;
                            }
                        }
                    }
                }
                if (subdir) {
                    closedir (subdir);
                }
            }
            usleep(100000);
            deadbeef->mutex_lock(thread_mutex);
        }
        if (covers_dir) {
            closedir (covers_dir);
            covers_dir = NULL;
        }

        /* Sleep until just after the oldest file expires */
        if (cache_expiry_seconds > 0 && !terminate) {
            struct timespec wake_time = {
                .tv_sec = time(NULL) + max(60, oldest_mtime - time(NULL) + cache_expiry_seconds),
                .tv_nsec = 999999
            };
            trace("Cache cleaner sleeping for %d seconds\n", max(60, oldest_mtime - time(NULL) + cache_expiry_seconds));
            pthread_cond_timedwait((pthread_cond_t *)thread_cond, (pthread_mutex_t *)thread_mutex, &wake_time);
        }

        /* Just go back to sleep if cache expiry is disabled */
        while (cache_expiry_seconds <= 0 && !terminate) {
            trace("Cache cleaner sleeping forever\n");
            pthread_cond_wait((pthread_cond_t *)thread_cond, (pthread_mutex_t *)thread_mutex);
        }
    }
    deadbeef->mutex_unlock(thread_mutex);
}

void cache_configchanged(void)
{
    const int32_t new_cache_expiry_seconds = deadbeef->conf_get_int("artwork.cache.period", 48) * 60 * 60;
    if (new_cache_expiry_seconds != cache_expiry_seconds) {
        deadbeef->mutex_lock(thread_mutex);
        cache_expiry_seconds = new_cache_expiry_seconds;
        deadbeef->cond_signal(thread_cond);
        deadbeef->mutex_unlock(thread_mutex);
    }
}

void stop_cache_cleaner(void)
{
    if (tid) {
        deadbeef->mutex_lock(thread_mutex);
        terminate = 1;
        deadbeef->cond_signal(thread_cond);
        deadbeef->mutex_unlock(thread_mutex);
        deadbeef->thread_join(tid);
        tid = 0;
        trace("Cache cleaner thread stopped\n");
    }

    if (thread_mutex) {
        deadbeef->mutex_free(thread_mutex);
        thread_mutex = 0;
    }

    if (thread_cond) {
        deadbeef->cond_free(thread_cond);
        thread_cond = 0;
    }

    if (files_mutex) {
        deadbeef->mutex_free(files_mutex);
        files_mutex = 0;
    }
}

int start_cache_cleaner(void)
{
    terminate = 0;
    cache_expiry_seconds = deadbeef->conf_get_int("artwork.cache.period", 48) * 60 * 60;
    files_mutex = deadbeef->mutex_create_nonrecursive();
    thread_mutex = deadbeef->mutex_create_nonrecursive();
    thread_cond = deadbeef->cond_create();
    if (files_mutex && thread_mutex && thread_cond) {
        tid = deadbeef->thread_start_low_priority(cache_cleaner_thread, NULL);
        trace("Cache cleaner thread started\n");
    }

    if (!tid) {
        stop_cache_cleaner();
        return -1;
    }

    return 0;
}
Ejemplo n.º 7
0
Archivo: redir.c Proyecto: lb1a/avfs
static char *resolv_virt(const char *pathname, int must_exist, int flags)
{
	struct nameidata root;
	struct nameidata nd;
	struct dentry *origroot;
	struct vfsmount *origrootmnt;
	char *newpathname = NULL;
	char *page = NULL;
	char *path = NULL;
	int pathlen = 0;
	int error;
	int newflags;

	lock_kernel();

	DEB((KERN_INFO "resolve_virt pathname: '%s'\n", 
	     pathname ? pathname : "(null)"));

	error = a_path_walk(OVERLAY_DIR, LOOKUP_POSITIVE|LOOKUP_FOLLOW, &root);
	if(error)
		goto out;

	origroot = current->fs->root;
	origrootmnt = current->fs->rootmnt;

	current->fs->root = root.dentry;
	current->fs->rootmnt = root.mnt;
	
	newflags = flags;
	if(must_exist)
		newflags |= LOOKUP_POSITIVE;

	error  = a_path_walk(pathname, newflags, &nd);
	if(!error) {
		if(path_ok(nd.dentry)) {
			page = (char *) __get_free_page(GFP_USER);
			if(page) {
				path = d_path(nd.dentry, nd.mnt, page,
					      PAGE_SIZE);
				DEB((KERN_INFO "resolve_virt path = '%s'\n",
				     path));
				pathlen = (unsigned int) page + PAGE_SIZE - 
					(unsigned int) path;
			}
		}
		a_path_release(&nd);
	}

	current->fs->root = origroot;
	current->fs->rootmnt = origrootmnt;

	a_path_release(&root);

	if(path) {
		int isvirtual;

		error  = a_path_walk(path, flags, &nd);
		if(!error) {
			if(nd.dentry->d_inode)
				isvirtual = 0;
			else if(must_exist)
				isvirtual = 1;
			else if(strchr(path, AVFS_MAGIC_CHAR))
				isvirtual = 1;
			else 
				isvirtual = 0;

			a_path_release(&nd);
		}
		else {
			isvirtual = 1;
		}

		if(!isvirtual) {
			newpathname = kmalloc(pathlen + 1, GFP_USER);
			if(newpathname)
				strncpy(newpathname, path, pathlen);
		}
		else {
			newpathname = kmalloc(OVERLAY_DIR_LEN + pathlen + 1,
					      GFP_USER);

			if(newpathname) {
				strcpy(newpathname, OVERLAY_DIR);
				strncat(newpathname, path, pathlen);
			}
		}
	}

	if(page)
		free_page((unsigned long) page);


	DEB((KERN_INFO "resolve_virt newpathname: '%s'\n", 
	     newpathname ? newpathname : "(null)"));

 out:
	unlock_kernel();
	return newpathname;
}
Ejemplo n.º 8
0
Archivo: redir.c Proyecto: lb1a/avfs
static char *resolv_virt(const char *pathname, int must_exist, int flags)
{
	struct dentry *root, *origroot;
	struct dentry *dentry;
	char *newpathname = NULL;
	char *page = NULL;
	char *path = NULL;
	int pathlen = 0;

	lock_kernel();

	DEB((KERN_INFO "resolve_virt pathname: '%s'\n", 
	     pathname ? pathname : "(null)"));

	root = lookup_dentry(OVERLAY_DIR, NULL, 1);
	if(IS_ERR(root))
		goto out;
	
	if(!root->d_inode) {
		dput(root);
		goto out;
	}

	origroot = current->fs->root;
	current->fs->root = root;
	
	dentry = lookup_dentry(pathname, NULL, flags);
	if(!IS_ERR(dentry)) {
		if((!must_exist || dentry->d_inode) && path_ok(dentry)) {
			page = (char *) __get_free_page(GFP_USER);
			if(page) {
				path = d_path(dentry, page, PAGE_SIZE);
				DEB((KERN_INFO "resolve_virt path = '%s'\n",
				     path));
				pathlen = (unsigned int) page + PAGE_SIZE - 
					(unsigned int) path;
			}
		}
		dput(dentry);
	}

	current->fs->root = origroot;
	dput(root);

	if(path) {
		int isvirtual;

		dentry = lookup_dentry(path, NULL, flags);

		if(!IS_ERR(dentry)) {
			if(dentry->d_inode)
				isvirtual = 0;
			else if(must_exist)
				isvirtual = 1;
			else if(strchr(path, AVFS_MAGIC_CHAR))
				isvirtual = 1;
			else 
				isvirtual = 0;

			dput(dentry);
		}
		else {
			isvirtual = 1;
		}

		if(!isvirtual) {
			newpathname = kmalloc(pathlen + 1, 
					      GFP_USER);
			if(newpathname)
				strncpy(newpathname, path, pathlen);
		}
		else {
			newpathname = kmalloc(OVERLAY_DIR_LEN + pathlen + 1,
					      GFP_USER);

			if(newpathname) {
				strcpy(newpathname, OVERLAY_DIR);
				strncat(newpathname, path, pathlen);
			}
		}
	}

	if(page)
		free_page((unsigned long) page);


	DEB((KERN_INFO "resolve_virt newpathname: '%s'\n", 
	     newpathname ? newpathname : "(null)"));

 out:
	unlock_kernel();
	return newpathname;
}