コード例 #1
0
ファイル: cfuns-c.c プロジェクト: pbroadbery/fricas-svn
int
remove_directory(char * name)
{
    DIR * cur_dir = opendir(".");
    DIR * dir;
    int cur_dir_fd;
    int dir_fd;
    struct dirent * entry;
    struct file_list {
        struct file_list * next;
        char * file;
    };
    struct file_list * flst = 0;
    if (!cur_dir) {
        fprintf(stderr, "Unable to open current directory\n");
        return -1;
    }
    dir = opendir(name);
    if (!dir) {
        fprintf(stderr, "Unable to open directory to be removed\n");
        goto err1;
    }
    cur_dir_fd = dirfd(cur_dir);
    dir_fd = dirfd(dir);
    if (cur_dir_fd == -1 || dir_fd == -1) {
        fprintf(stderr, "dirfd failed\n");
        goto err2;
    }
    while ((entry = readdir(dir))) {
        char * fname = &(entry->d_name[0]);
        if (!strcmp(fname, ".")) { 
            continue; 
        } else if (!strcmp(fname, "..")) {
            continue;
        } else {
            struct file_list * npos = malloc(sizeof(*npos));
            if (!npos) {
                fprintf(stderr, "Malloc failed (npos)\n");
                break;
            }
            npos->file = copy_string(fname);
            if (!(npos->file)) {
                free(npos);
                break;
            }
            npos->next = flst;
            flst = npos;
        }
    }
    if (fchdir(dir_fd)) {
        perror("Failed to change directory to directory to be removed");
        while (flst) {
            struct file_list * npos = flst->next;
            free(flst->file);
            free(flst);
            flst = npos;
        }
        goto err2;
    }
    while (flst) {
        struct file_list * npos = flst->next;
        if (unlink(flst->file)) {
	    perror("Unlink failed");
        }
        free(flst->file);
        free(flst);
        flst = npos;
    }
    if (fchdir(cur_dir_fd)) {
        closedir(dir);
        closedir(cur_dir);
        return -1;
    }
  err2:
    closedir(dir);
  err1:
    closedir(cur_dir);
    {
        int res = rmdir(name);
        if (res) {
            perror("rmdir failed");
        }
        return res;
    }
}
コード例 #2
0
int DirInit (access_t *p_access, DIR *handle)
{
    access_sys_t *p_sys = malloc (sizeof (*p_sys));
    if (unlikely(p_sys == NULL))
        goto error;

    char *uri;
    if (!strcmp (p_access->psz_access, "fd"))
    {
        if (asprintf (&uri, "fd://%s", p_access->psz_location) == -1)
            uri = NULL;
    }
    else
        uri = vlc_path2uri (p_access->psz_filepath, "file");
    if (unlikely(uri == NULL))
        goto error;

    /* "Open" the base directory */
    directory_t *root = malloc (sizeof (*root));
    if (unlikely(root == NULL))
    {
        free (uri);
        goto error;
    }

    char *psz_sort = var_InheritString (p_access, "directory-sort");
    if (!psz_sort)
        p_sys->compar = collate;
    else if (!strcasecmp (psz_sort, "version"))
        p_sys->compar = version;
    else if (!strcasecmp (psz_sort, "none"))
        p_sys->compar = NULL;
    else
        p_sys->compar = collate;
    free(psz_sort);

    root->parent = NULL;
    root->handle = handle;
    root->uri = uri;
    root->filec = vlc_loaddir (handle, &root->filev, visible, p_sys->compar);
    if (root->filec < 0)
        root->filev = NULL;
    root->i = 0;
#ifdef HAVE_OPENAT
    struct stat st;
    if (fstat (dirfd (handle), &st))
    {
        free (root);
        free (uri);
        goto error;
    }
    root->device = st.st_dev;
    root->inode = st.st_ino;
#else
    root->path = strdup (p_access->psz_filepath);
#endif

    p_access->p_sys = p_sys;
    p_sys->current = root;
    p_sys->ignored_exts = var_InheritString (p_access, "ignore-filetypes");
    p_sys->header = true;
    p_sys->i_item_count = 0;
    p_sys->xspf_ext = strdup ("");

    /* Handle mode */
    char *psz = var_InheritString (p_access, "recursive");
    if (psz == NULL || !strcasecmp (psz, "none"))
        p_sys->mode = MODE_NONE;
    else if( !strcasecmp( psz, "collapse" )  )
        p_sys->mode = MODE_COLLAPSE;
    else
        p_sys->mode = MODE_EXPAND;
    free( psz );

    access_InitFields(p_access);
    p_access->pf_read  = NULL;
    p_access->pf_block = DirBlock;
    p_access->pf_seek  = NULL;
    p_access->pf_control= DirControl;
    free (p_access->psz_demux);
    p_access->psz_demux = strdup ("xspf-open");

    return VLC_SUCCESS;

error:
    closedir (handle);
    free (p_sys);
    return VLC_EGENERIC;
}
コード例 #3
0
ファイル: rwho.c プロジェクト: ChaosJohn/freebsd
int
main(int argc, char *argv[])
{
	int ch;
	struct dirent *dp;
	int width;
	ssize_t cc;
	struct whod *w;
	struct whoent *we;
	struct myutmp *mp;
	cap_rights_t rights;
	int f, n, i;
	int d_first;
	int dfd;
	time_t ct;

	w = &wd;
	(void) setlocale(LC_TIME, "");
	d_first = (*nl_langinfo(D_MD_ORDER) == 'd');

	while ((ch = getopt(argc, argv, "a")) != -1) {
		switch ((char)ch) {
		case 'a':
			aflg = 1;
			break;
		case '?':
		default:
			usage();
		}
	}
	argc -= optind;
	argv += optind;

	if (argc != 0)
		usage();

	if (chdir(_PATH_RWHODIR) < 0)
		err(1, "chdir(%s)", _PATH_RWHODIR);
	if ((dirp = opendir(".")) == NULL)
		err(1, "opendir(%s)", _PATH_RWHODIR);
	dfd = dirfd(dirp);
	mp = myutmp;
	cap_rights_init(&rights, CAP_READ, CAP_LOOKUP);
	if (cap_rights_limit(dfd, &rights) < 0 && errno != ENOSYS)
		err(1, "cap_rights_limit failed: %s", _PATH_RWHODIR);
	/*
	 * Cache files required for time(3) and localtime(3) before entering
	 * capability mode.
	 */
	(void) time(&ct);
	(void) localtime(&ct);
	if (cap_enter() < 0 && errno != ENOSYS)
		err(1, "cap_enter");
	(void) time(&now);
	cap_rights_init(&rights, CAP_READ);
	while ((dp = readdir(dirp)) != NULL) {
		if (dp->d_ino == 0 || strncmp(dp->d_name, "whod.", 5) != 0)
			continue;
		f = openat(dfd, dp->d_name, O_RDONLY);
		if (f < 0)
			continue;
		if (cap_rights_limit(f, &rights) < 0 && errno != ENOSYS)
			err(1, "cap_rights_limit failed: %s", dp->d_name);
		cc = read(f, (char *)&wd, sizeof(struct whod));
		if (cc < WHDRSIZE) {
			(void) close(f);
			continue;
		}
		if (down(w, now) != 0) {
			(void) close(f);
			continue;
		}
		cc -= WHDRSIZE;
		we = w->wd_we;
		for (n = cc / sizeof(struct whoent); n > 0; n--) {
			if (aflg == 0 && we->we_idle >= 60 * 60) {
				we++;
				continue;
			}
			if (nusers >= NUSERS)
				errx(1, "too many users");
			mp->myutmp = we->we_utmp;
			mp->myidle = we->we_idle;
			(void) strcpy(mp->myhost, w->wd_hostname);
			nusers++;
			we++;
			mp++;
		}
		(void) close(f);
	}
	qsort((char *)myutmp, nusers, sizeof(struct myutmp), utmpcmp);
	mp = myutmp;
	width = 0;
	for (i = 0; i < nusers; i++) {
		/* append one for the blank and use 8 for the out_line */
		int j;

		j = strlen(mp->myhost) + 1 + sizeof(mp->myutmp.out_line);
		if (j > width)
			width = j;
		mp++;
	}
	mp = myutmp;
	for (i = 0; i < nusers; i++) {
		char buf[BUFSIZ], cbuf[80];
		time_t t;

		t = _int_to_time(mp->myutmp.out_time);
		strftime(cbuf, sizeof(cbuf), d_first ? "%e %b %R" : "%b %e %R",
		    localtime(&t));
		(void) sprintf(buf, "%s:%-.*s", mp->myhost,
		    (int)sizeof(mp->myutmp.out_line), mp->myutmp.out_line);
		printf("%-*.*s %-*s %s",
		    (int)sizeof(mp->myutmp.out_name),
		    (int)sizeof(mp->myutmp.out_name),
		    mp->myutmp.out_name, width, buf, cbuf);
		mp->myidle /= 60;
		if (mp->myidle != 0) {
			if (aflg != 0) {
				if (mp->myidle >= 100 * 60)
					mp->myidle = 100 * 60 - 1;
				if (mp->myidle >= 60)
					printf(" %2d", mp->myidle / 60);
				else
					printf("   ");
			} else {
				printf(" ");
			}
			printf(":%02d", mp->myidle % 60);
		}
		printf("\n");
		mp++;
	}
	exit(0);
}
コード例 #4
0
ファイル: commands.c プロジェクト: AOSPLUS/frameworks_native
int get_size(const char *pkgname, userid_t userid, const char *apkpath,
             const char *libdirpath, const char *fwdlock_apkpath, const char *asecpath,
             int64_t *_codesize, int64_t *_datasize, int64_t *_cachesize,
             int64_t* _asecsize)
{
    DIR *d;
    int dfd;
    struct dirent *de;
    struct stat s;
    char path[PKG_PATH_MAX];

    int64_t codesize = 0;
    int64_t datasize = 0;
    int64_t cachesize = 0;
    int64_t asecsize = 0;

        /* count the source apk as code -- but only if it's not
         * on the /system partition and its not on the sdcard.
         */
    if (validate_system_app_path(apkpath) &&
            strncmp(apkpath, android_asec_dir.path, android_asec_dir.len) != 0) {
        if (stat(apkpath, &s) == 0) {
            codesize += stat_size(&s);
        }
    }
        /* count the forward locked apk as code if it is given
         */
    if (fwdlock_apkpath != NULL && fwdlock_apkpath[0] != '!') {
        if (stat(fwdlock_apkpath, &s) == 0) {
            codesize += stat_size(&s);
        }
    }
        /* count the cached dexfile as code */
    if (!create_cache_path(path, apkpath)) {
        if (stat(path, &s) == 0) {
            codesize += stat_size(&s);
        }
    }

        /* add in size of any libraries */
    if (libdirpath != NULL && libdirpath[0] != '!') {
        d = opendir(libdirpath);
        if (d != NULL) {
            dfd = dirfd(d);
            codesize += calculate_dir_size(dfd);
            closedir(d);
        }
    }

        /* compute asec size if it is given
         */
    if (asecpath != NULL && asecpath[0] != '!') {
        if (stat(asecpath, &s) == 0) {
            asecsize += stat_size(&s);
        }
    }

    if (create_pkg_path(path, pkgname, PKG_DIR_POSTFIX, userid)) {
        goto done;
    }

    d = opendir(path);
    if (d == NULL) {
        goto done;
    }
    dfd = dirfd(d);

    /* most stuff in the pkgdir is data, except for the "cache"
     * directory and below, which is cache, and the "lib" directory
     * and below, which is code...
     */
    while ((de = readdir(d))) {
        const char *name = de->d_name;

        if (de->d_type == DT_DIR) {
            int subfd;
            int64_t statsize = 0;
            int64_t dirsize = 0;
                /* always skip "." and ".." */
            if (name[0] == '.') {
                if (name[1] == 0) continue;
                if ((name[1] == '.') && (name[2] == 0)) continue;
            }
            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
                statsize = stat_size(&s);
            }
            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
            if (subfd >= 0) {
                dirsize = calculate_dir_size(subfd);
            }
            if(!strcmp(name,"lib")) {
                codesize += dirsize + statsize;
            } else if(!strcmp(name,"cache")) {
                cachesize += dirsize + statsize;
            } else {
                datasize += dirsize + statsize;
            }
        } else if (de->d_type == DT_LNK && !strcmp(name,"lib")) {
            // This is the symbolic link to the application's library
            // code.  We'll count this as code instead of data, since
            // it is not something that the app creates.
            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
                codesize += stat_size(&s);
            }
        } else {
            if (fstatat(dfd, name, &s, AT_SYMLINK_NOFOLLOW) == 0) {
                datasize += stat_size(&s);
            }
        }
    }
    closedir(d);
done:
    *_codesize = codesize;
    *_datasize = datasize;
    *_cachesize = cachesize;
    *_asecsize = asecsize;
    return 0;
}
コード例 #5
0
static bool is_card_busy(const char *id) {
    char *card_path = NULL, *pcm_path = NULL, *sub_status = NULL;
    DIR *card_dir = NULL, *pcm_dir = NULL;
    FILE *status_file = NULL;
    size_t len;
    struct dirent *space = NULL, *de;
    bool busy = false;
    int r;

    pa_assert(id);

    /* This simply uses /proc/asound/card.../pcm.../sub.../status to
     * check whether there is still a process using this audio device. */

    card_path = pa_sprintf_malloc("/proc/asound/card%s", id);

    if (!(card_dir = opendir(card_path))) {
        pa_log_warn("Failed to open %s: %s", card_path, pa_cstrerror(errno));
        goto fail;
    }

    len = offsetof(struct dirent, d_name) + fpathconf(dirfd(card_dir), _PC_NAME_MAX) + 1;
    space = pa_xmalloc(len);

    for (;;) {
        de = NULL;

        if ((r = readdir_r(card_dir, space, &de)) != 0) {
            pa_log_warn("readdir_r() failed: %s", pa_cstrerror(r));
            goto fail;
        }

        if (!de)
            break;

        if (!pa_startswith(de->d_name, "pcm"))
            continue;

        if (pcm_is_modem(id, de->d_name + 3))
            continue;

        pa_xfree(pcm_path);
        pcm_path = pa_sprintf_malloc("%s/%s", card_path, de->d_name);

        if (pcm_dir)
            closedir(pcm_dir);

        if (!(pcm_dir = opendir(pcm_path))) {
            pa_log_warn("Failed to open %s: %s", pcm_path, pa_cstrerror(errno));
            continue;
        }

        for (;;) {
            char line[32];

            if ((r = readdir_r(pcm_dir, space, &de)) != 0) {
                pa_log_warn("readdir_r() failed: %s", pa_cstrerror(r));
                goto fail;
            }

            if (!de)
                break;

            if (!pa_startswith(de->d_name, "sub"))
                continue;

            pa_xfree(sub_status);
            sub_status = pa_sprintf_malloc("%s/%s/status", pcm_path, de->d_name);

            if (status_file)
                fclose(status_file);

            if (!(status_file = pa_fopen_cloexec(sub_status, "r"))) {
                pa_log_warn("Failed to open %s: %s", sub_status, pa_cstrerror(errno));
                continue;
            }

            if (!(fgets(line, sizeof(line)-1, status_file))) {
                pa_log_warn("Failed to read from %s: %s", sub_status, pa_cstrerror(errno));
                continue;
            }

            if (!pa_streq(line, "closed\n")) {
                busy = true;
                break;
            }
        }
    }

fail:

    pa_xfree(card_path);
    pa_xfree(pcm_path);
    pa_xfree(sub_status);
    pa_xfree(space);

    if (card_dir)
        closedir(card_dir);

    if (pcm_dir)
        closedir(pcm_dir);

    if (status_file)
        fclose(status_file);

    return busy;
}
コード例 #6
0
ファイル: fts.cpp プロジェクト: noscripter/tomita-parser
/*
 * This is the tricky part -- do not casually change *anything* in here.  The
 * idea is to build the linked list of entries that are used by yfts_children
 * and yfts_read.  There are lots of special cases.
 *
 * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is
 * set and it's a physical walk (so that symbolic links can't be directories),
 * we can do things quickly.  First, if it's a 4.4BSD file system, the type
 * of the file is in the directory entry.  Otherwise, we assume that the number
 * of subdirectories in a node is equal to the number of links to the parent.
 * The former skips all stat calls.  The latter skips stat calls in any leaf
 * directories and for any files after the subdirectories in the directory have
 * been found, cutting the stat calls by about 2/3.
 */
static FTSENT *
fts_build(FTS * sp, int type)
{
    struct dirent *dp;
    FTSENT *p, *head;
    int nitems;
    FTSENT *cur, *tail;

#ifdef _win_
    dird dirpd;
    struct DIR *dirp;
#else
    DIR *dirp;
#endif

    void *oldaddr;
    int cderrno, descend, len, level, maxlen, nlinks, saved_errno,
        nostat, doadjust;
    char *cp;

    /* Set current node pointer. */
    cur = sp->fts_cur;

    /*
     * Open the directory for reading.  If this fails, we're done.
     * If being called from yfts_read, set the fts_info field.
     */
#ifdef FTS_WHITEOUT
    if (ISSET(FTS_WHITEOUT))
        oflag = DTF_NODUP|DTF_REWIND;
    else
        oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
#else
#define __opendir2(path, flag) opendir(path)
#endif
    if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
        if (type == BREAD) {
            cur->fts_info = FTS_DNR;
            cur->fts_errno = errno;
        }
        return (NULL);
    }

#ifdef _win_
    dirpd = get_dird(cur->fts_accpath);
#endif

    /*
     * Nlinks is the number of possible entries of type directory in the
     * directory if we're cheating on stat calls, 0 if we're not doing
     * any stat calls at all, -1 if we're doing stats on everything.
     */
    if (type == BNAMES) {
        nlinks = 0;
        /* Be quiet about nostat, GCC. */
        nostat = 0;
    } else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
        nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
        nostat = 1;
    } else {
        nlinks = -1;
        nostat = 0;
    }

#ifdef notdef
    (void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
    (void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
                 ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
#endif
    /*
     * If we're going to need to stat anything or we want to descend
     * and stay in the directory, chdir.  If this fails we keep going,
     * but set a flag so we don't chdir after the post-order visit.
     * We won't be able to stat anything, but we can still return the
     * names themselves.  Note, that since yfts_read won't be able to
     * chdir into the directory, it will have to return different path
     * names than before, i.e. "a/b" instead of "b".  Since the node
     * has already been visited in pre-order, have to wait until the
     * post-order visit to return the error.  There is a special case
     * here, if there was nothing to stat then it's not an error to
     * not be able to stat.  This is all fairly nasty.  If a program
     * needed sorted entries or stat information, they had better be
     * checking FTS_NS on the returned nodes.
     */
    cderrno = 0;
    if (nlinks || type == BREAD) {
#ifndef _win_
        if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
#else
        if (fts_safe_changedir(sp, cur, -1, dirpd)) {
#endif

            if (nlinks && type == BREAD)
                cur->fts_errno = errno;
            cur->fts_flags |= FTS_DONTCHDIR;
            descend = 0;
            cderrno = errno;
            (void)closedir(dirp);
            dirp = NULL;
#ifdef _win_
            close_dird(dirpd);
            dirpd = invalidDirD;
#else
            UNUSED(invalidDirD);
#endif
        } else
            descend = 1;
    } else
        descend = 0;

    /*
     * Figure out the max file name length that can be stored in the
     * current path -- the inner loop allocates more path as necessary.
     * We really wouldn't have to do the maxlen calculations here, we
     * could do them in yfts_read before returning the path, but it's a
     * lot easier here since the length is part of the dirent structure.
     *
     * If not changing directories set a pointer so that can just append
     * each new name into the path.
     */
    len = NAPPEND(cur);
    if (ISSET(FTS_NOCHDIR)) {
        cp = sp->fts_path + len;
        *cp++ = LOCSLASH_C;
    } else {
        /* GCC, you're too verbose. */
        cp = NULL;
    }
    len++;
    maxlen = sp->fts_pathlen - len;

    level = cur->fts_level + 1;

    /* Read the directory, attaching each entry to the `link' pointer. */
    doadjust = 0;

    //to ensure enough buffer
    TTempBuf dpe;

    for (head = tail = NULL, nitems = 0; dirp && (dp = yreaddir(dirp, (struct dirent*)dpe.Data())) != 0;) {
        if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
            continue;

        if ((p = fts_alloc(sp, dp->d_name, (int)strlen(dp->d_name))) == NULL)
            goto mem1;
        if (strlen(dp->d_name) >= (size_t)maxlen) {    /* include space for NUL */
            oldaddr = sp->fts_path;
            if (fts_palloc(sp, strlen(dp->d_name) +len + 1)) {
                /*
                 * No more memory for path or structures.  Save
                 * errno, free up the current structure and the
                 * structures already allocated.
                 */
mem1:
                saved_errno = errno;
                if (p)
                    free(p);
                fts_lfree(head);
                (void)closedir(dirp);
#ifdef _win_
                close_dird(dirpd);
#endif
                cur->fts_info = FTS_ERR;
                SET(FTS_STOP);
                errno = saved_errno;
                return (NULL);
            }
            /* Did realloc() change the pointer? */
            if (oldaddr != sp->fts_path) {
                doadjust = 1;
                if (ISSET(FTS_NOCHDIR))
                    cp = sp->fts_path + len;
            }
            maxlen = sp->fts_pathlen - len;
        }

        if (len + strlen(dp->d_name) >= USHRT_MAX) {
            /*
             * In an FTSENT, fts_pathlen is a u_short so it is
             * possible to wraparound here.  If we do, free up
             * the current structure and the structures already
             * allocated, then error out with ENAMETOOLONG.
             */
            free(p);
            fts_lfree(head);
            (void)closedir(dirp);
#ifdef _win_
            close_dird(dirpd);
#endif
            cur->fts_info = FTS_ERR;
            SET(FTS_STOP);
            errno = ENAMETOOLONG;
            return (NULL);
        }
        p->fts_level = (short)level;
        p->fts_parent = sp->fts_cur;
        p->fts_pathlen = u_short(len + strlen(dp->d_name));

#ifdef FTS_WHITEOUT
        if (dp->d_type == DT_WHT)
            p->fts_flags |= FTS_ISW;
#endif

        if (cderrno) {
            if (nlinks) {
                p->fts_info = FTS_NS;
                p->fts_errno = cderrno;
            } else
                p->fts_info = FTS_NSOK;
            p->fts_accpath = cur->fts_accpath;
        } else if (nlinks == 0
#ifdef DT_DIR
                   || (nostat &&
                       dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
#endif
                  ) {
            p->fts_accpath =
                ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
            p->fts_info = FTS_NSOK;
        } else {
            /* Build a file name for fts_stat to stat. */
            if (ISSET(FTS_NOCHDIR)) {
                p->fts_accpath = p->fts_path;
                memmove((void*)cp, (void*)p->fts_name, (size_t)p->fts_namelen + 1);
            } else
                p->fts_accpath = p->fts_name;
            /* Stat it. */
            p->fts_info = fts_stat(sp, p, 0);

            /* Decrement link count if applicable. */
            if (nlinks > 0 && (p->fts_info == FTS_D ||
                               p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
                --nlinks;
        }

        /* We walk in directory order so "ls -f" doesn't get upset. */
        p->fts_link = NULL;
        if (head == NULL)
            head = tail = p;
        else {
            tail->fts_link = p;
            tail = p;
        }
        ++nitems;
    }
    if (dirp) {
        (void)closedir(dirp);
#ifdef _win_
        close_dird(dirpd);
#endif
    }

    /*
     * If realloc() changed the address of the path, adjust the
     * addresses for the rest of the tree and the dir list.
     */
    if (doadjust)
        fts_padjust(sp);

    /*
     * If not changing directories, reset the path back to original
     * state.
     */
    if (ISSET(FTS_NOCHDIR)) {
        if (len == sp->fts_pathlen || nitems == 0)
            --cp;
        *cp = '\0';
    }

    /*
     * If descended after called from yfts_children or after called from
     * yfts_read and nothing found, get back.  At the root level we use
     * the saved fd; if one of yfts_open()'s arguments is a relative path
     * to an empty directory, we wind up here with no other way back.  If
     * can't get back, we're done.
     */
    if (descend && (type == BCHILD || !nitems) &&
            (cur->fts_level == FTS_ROOTLEVEL ?
             FCHDIR(sp, sp->fts_rfd) :
             fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
        cur->fts_info = FTS_ERR;
        SET(FTS_STOP);
        return (NULL);
    }

    /* If didn't find anything, return NULL. */
    if (!nitems) {
        if (type == BREAD)
            cur->fts_info = FTS_DP;
        return (NULL);
    }

    /* Sort the entries. */
    if (sp->fts_compar && nitems > 1)
        head = fts_sort(sp, head, nitems);
    return (head);
}

static u_short
fts_stat(FTS * sp, FTSENT * p, int follow)
{
    dev_t dev;
    ino_t ino;
    struct stat *sbp, sb;
    int saved_errno;
    /* If user needs stat info, stat buffer already allocated. */
    sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;

#ifdef FTS_WHITEOUT
    /* check for whiteout */
    if (p->fts_flags & FTS_ISW) {
        if (sbp != &sb) {
            memset(sbp, '\0', sizeof (*sbp));
            sbp->st_mode = S_IFWHT;
        }
        return (FTS_W);
    }
#endif

    /*
     * If doing a logical walk, or application requested FTS_FOLLOW, do
     * a stat(2).  If that fails, check for a non-existent symlink.  If
     * fail, set the errno from the stat call.
     */
    if (ISSET(FTS_LOGICAL) || follow) {
        if (stat(p->fts_accpath, sbp)) {
            saved_errno = errno;
            if (!lstat(p->fts_accpath, sbp)) {
                errno = 0;
                return (FTS_SLNONE);
            }
            p->fts_errno = saved_errno;
            memset(sbp, 0, sizeof(struct stat));
            return (FTS_NS);
        }
    }
    else if (lstat(p->fts_accpath, sbp)) {
        p->fts_errno = errno;
        memset(sbp, 0, sizeof(struct stat));
        return (FTS_NS);
    }

    if (S_ISDIR(sbp->st_mode)) {
        /*
         * Set the device/inode.  Used to find cycles and check for
         * crossing mount points.  Also remember the link count, used
         * in fts_build to limit the number of stat calls.  It is
         * understood that these fields are only referenced if fts_info
         * is set to FTS_D.
         */
        dev = p->fts_dev = sbp->st_dev;
        ino = p->fts_ino = sbp->st_ino;
        p->fts_nlink = sbp->st_nlink;

        const char* fts_name_x = p->fts_name;
        if (ISDOT(fts_name_x))
            return (FTS_DOT);

        /*
         * Cycle detection is done by brute force when the directory
         * is first encountered.  If the tree gets deep enough or the
         * number of symbolic links to directories is high enough,
         * something faster might be worthwhile.
         */

        //There is no way to detect symlink or mount cycles on win32

#ifndef _win_
        FTSENT *t;
        for (t = p->fts_parent;
                t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
            if (ino == t->fts_ino && dev == t->fts_dev) {
                p->fts_cycle = t;
                return (FTS_DC);
            }
#endif /*_win_*/
        return (FTS_D);

    }
    if (S_ISLNK(sbp->st_mode))
        return (FTS_SL);
    if (S_ISREG(sbp->st_mode))
        return (FTS_F);
    return (FTS_DEFAULT);
}
コード例 #7
0
ファイル: utils.c プロジェクト: 777rom/777_frameworks_base
static int _add_cache_files(cache_t *cache, cache_dir_t *parentDir, const char *dirName,
        DIR* dir, char *pathBase, char *pathPos, size_t pathAvailLen)
{
    struct dirent *de;
    cache_dir_t* cacheDir = NULL;
    int dfd;

    CACHE_NOISY(ALOGI("_add_cache_files: parent=%p dirName=%s dir=%p pathBase=%s",
            parentDir, dirName, dir, pathBase));

    dfd = dirfd(dir);

    if (dfd < 0) return 0;

    // Sub-directories always get added to the data structure, so if they
    // are empty we will know about them to delete them later.
    cacheDir = _add_cache_dir_t(cache, parentDir, dirName);

    while ((de = readdir(dir))) {
        const char *name = de->d_name;

        if (de->d_type == DT_DIR) {
            int subfd;
            DIR *subdir;

                /* always skip "." and ".." */
            if (name[0] == '.') {
                if (name[1] == 0) continue;
                if ((name[1] == '.') && (name[2] == 0)) continue;
            }

            subfd = openat(dfd, name, O_RDONLY | O_DIRECTORY);
            if (subfd < 0) {
                ALOGE("Couldn't openat %s: %s\n", name, strerror(errno));
                continue;
            }
            subdir = fdopendir(subfd);
            if (subdir == NULL) {
                ALOGE("Couldn't fdopendir %s: %s\n", name, strerror(errno));
                close(subfd);
                continue;
            }
            if (cacheDir == NULL) {
                cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
            }
            if (cacheDir != NULL) {
                // Update pathBase for the new path...  this may change dirName
                // if that is also pointing to the path, but we are done with it
                // now.
                size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
                CACHE_NOISY(ALOGI("Collecting dir %s\n", pathBase));
                if (finallen < pathAvailLen) {
                    _add_cache_files(cache, cacheDir, name, subdir, pathBase,
                            pathPos+finallen, pathAvailLen-finallen);
                } else {
                    // Whoops, the final path is too long!  We'll just delete
                    // this directory.
                    ALOGW("Cache dir %s truncated in path %s; deleting dir\n",
                            name, pathBase);
                    _delete_dir_contents(subdir, NULL);
                    if (unlinkat(dfd, name, AT_REMOVEDIR) < 0) {
                        ALOGE("Couldn't unlinkat %s: %s\n", name, strerror(errno));
                    }
                }
            }
            closedir(subdir);
        } else if (de->d_type == DT_REG) {
            // Skip files that start with '.'; they will be deleted if
            // their entire directory is deleted.  This allows for metadata
            // like ".nomedia" to remain in the directory until the entire
            // directory is deleted.
            if (cacheDir == NULL) {
                cacheDir = _add_cache_dir_t(cache, parentDir, dirName);
            }
            if (name[0] == '.') {
                cacheDir->hiddenCount++;
                continue;
            }
            if (cacheDir != NULL) {
                // Build final full path for file...  this may change dirName
                // if that is also pointing to the path, but we are done with it
                // now.
                size_t finallen = snprintf(pathPos, pathAvailLen, "/%s", name);
                CACHE_NOISY(ALOGI("Collecting file %s\n", pathBase));
                if (finallen < pathAvailLen) {
                    struct stat s;
                    if (stat(pathBase, &s) >= 0) {
                        _add_cache_file_t(cache, cacheDir, s.st_mtime, name);
                    } else {
                        ALOGW("Unable to stat cache file %s; deleting\n", pathBase);
                        if (unlink(pathBase) < 0) {
                            ALOGE("Couldn't unlink %s: %s\n", pathBase, strerror(errno));
                        }
                    }
                } else {
                    // Whoops, the final path is too long!  We'll just delete
                    // this file.
                    ALOGW("Cache file %s truncated in path %s; deleting\n",
                            name, pathBase);
                    if (unlinkat(dfd, name, 0) < 0) {
                        *pathPos = 0;
                        ALOGE("Couldn't unlinkat %s in %s: %s\n", name, pathBase,
                                strerror(errno));
                    }
                }
            }
        } else {
            cacheDir->hiddenCount++;
        }
    }
    return 0;
}
コード例 #8
0
ファイル: be_local.c プロジェクト: AWhetter/pacman
static int local_db_populate(alpm_db_t *db)
{
	size_t est_count;
	int count = 0;
	struct stat buf;
	struct dirent *ent = NULL;
	const char *dbpath;
	DIR *dbdir;

	if(db->status & DB_STATUS_INVALID) {
		RET_ERR(db->handle, ALPM_ERR_DB_INVALID, -1);
	}
	if(db->status & DB_STATUS_MISSING) {
		RET_ERR(db->handle, ALPM_ERR_DB_NOT_FOUND, -1);
	}

	dbpath = _alpm_db_path(db);
	if(dbpath == NULL) {
		/* pm_errno set in _alpm_db_path() */
		return -1;
	}

	dbdir = opendir(dbpath);
	if(dbdir == NULL) {
		RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1);
	}
	if(fstat(dirfd(dbdir), &buf) != 0) {
		RET_ERR(db->handle, ALPM_ERR_DB_OPEN, -1);
	}
	db->status |= DB_STATUS_EXISTS;
	db->status &= ~DB_STATUS_MISSING;
	if(buf.st_nlink >= 2) {
		est_count = buf.st_nlink;
	} else {
		/* Some filesystems don't subscribe to the two-implicit links school of
		 * thought, e.g. BTRFS, HFS+. See
		 * http://kerneltrap.org/mailarchive/linux-btrfs/2010/1/23/6723483/thread
		 */
		est_count = 0;
		while(readdir(dbdir) != NULL) {
			est_count++;
		}
		rewinddir(dbdir);
	}
	if(est_count >= 2) {
		/* subtract the '.' and '..' pointers to get # of children */
		est_count -= 2;
	}

	db->pkgcache = _alpm_pkghash_create(est_count);
	if(db->pkgcache == NULL){
		closedir(dbdir);
		RET_ERR(db->handle, ALPM_ERR_MEMORY, -1);
	}

	while((ent = readdir(dbdir)) != NULL) {
		const char *name = ent->d_name;

		alpm_pkg_t *pkg;

		if(strcmp(name, ".") == 0 || strcmp(name, "..") == 0) {
			continue;
		}
		if(!is_dir(dbpath, ent)) {
			continue;
		}

		pkg = _alpm_pkg_new();
		if(pkg == NULL) {
			closedir(dbdir);
			RET_ERR(db->handle, ALPM_ERR_MEMORY, -1);
		}
		/* split the db entry name */
		if(_alpm_splitname(name, &(pkg->name), &(pkg->version),
					&(pkg->name_hash)) != 0) {
			_alpm_log(db->handle, ALPM_LOG_ERROR, _("invalid name for database entry '%s'\n"),
					name);
			_alpm_pkg_free(pkg);
			continue;
		}

		/* duplicated database entries are not allowed */
		if(_alpm_pkghash_find(db->pkgcache, pkg->name)) {
			_alpm_log(db->handle, ALPM_LOG_ERROR, _("duplicated database entry '%s'\n"), pkg->name);
			_alpm_pkg_free(pkg);
			continue;
		}

		pkg->origin = ALPM_PKG_FROM_LOCALDB;
		pkg->origin_data.db = db;
		pkg->ops = &local_pkg_ops;
		pkg->handle = db->handle;

		/* explicitly read with only 'BASE' data, accessors will handle the rest */
		if(local_db_read(pkg, INFRQ_BASE) == -1) {
			_alpm_log(db->handle, ALPM_LOG_ERROR, _("corrupted database entry '%s'\n"), name);
			_alpm_pkg_free(pkg);
			continue;
		}

		/* add to the collection */
		_alpm_log(db->handle, ALPM_LOG_FUNCTION, "adding '%s' to package cache for db '%s'\n",
				pkg->name, db->treename);
		db->pkgcache = _alpm_pkghash_add(db->pkgcache, pkg);
		count++;
	}

	closedir(dbdir);
	if(count > 0) {
		db->pkgcache->list = alpm_list_msort(db->pkgcache->list, (size_t)count, _alpm_pkg_cmp);
	}
	_alpm_log(db->handle, ALPM_LOG_DEBUG, "added %d packages to package cache for db '%s'\n",
			count, db->treename);

	return count;
}
コード例 #9
0
ファイル: eal_hugepage_info.c プロジェクト: fleitner/dpdk
/*
 * Clear the hugepage directory of whatever hugepage files
 * there are. Checks if the file is locked (i.e.
 * if it's in use by another DPDK process).
 */
static int
clear_hugedir(const char * hugedir)
{
	DIR *dir;
	struct dirent *dirent;
	int dir_fd, fd, lck_result;
	const char filter[] = "*map_*"; /* matches hugepage files */

	/* open directory */
	dir = opendir(hugedir);
	if (!dir) {
		RTE_LOG(INFO, EAL, "Unable to open hugepage directory %s\n",
				hugedir);
		goto error;
	}
	dir_fd = dirfd(dir);

	dirent = readdir(dir);
	if (!dirent) {
		RTE_LOG(INFO, EAL, "Unable to read hugepage directory %s\n",
				hugedir);
		goto error;
	}

	while(dirent != NULL){
		/* skip files that don't match the hugepage pattern */
		if (fnmatch(filter, dirent->d_name, 0) > 0) {
			dirent = readdir(dir);
			continue;
		}

		/* try and lock the file */
		fd = openat(dir_fd, dirent->d_name, O_RDONLY);

		/* skip to next file */
		if (fd == -1) {
			dirent = readdir(dir);
			continue;
		}

		/* non-blocking lock */
		lck_result = flock(fd, LOCK_EX | LOCK_NB);

		/* if lock succeeds, unlock and remove the file */
		if (lck_result != -1) {
			flock(fd, LOCK_UN);
			unlinkat(dir_fd, dirent->d_name, 0);
		}
		close (fd);
		dirent = readdir(dir);
	}

	closedir(dir);
	return 0;

error:
	if (dir)
		closedir(dir);

	RTE_LOG(INFO, EAL, "Error while clearing hugepage dir: %s\n",
		strerror(errno));

	return -1;
}
コード例 #10
0
static int translate_ext_labels(struct fstab_rec *rec)
{
    DIR *blockdir = NULL;
    struct dirent *ent;
    char *label;
    size_t label_len;
    int ret = -1;

    if (strncmp(rec->blk_device, "LABEL=", 6))
        return 0;

    label = rec->blk_device + 6;
    label_len = strlen(label);

    if (label_len > 16) {
        ERROR("FS label is longer than allowed by filesystem\n");
        goto out;
    }


    blockdir = opendir("/dev/block");
    if (!blockdir) {
        ERROR("couldn't open /dev/block\n");
        goto out;
    }

    while ((ent = readdir(blockdir))) {
        int fd;
        char super_buf[1024];
        struct ext4_super_block *sb;

        if (ent->d_type != DT_BLK)
            continue;

        fd = openat(dirfd(blockdir), ent->d_name, O_RDONLY);
        if (fd < 0) {
            ERROR("Cannot open block device /dev/block/%s\n", ent->d_name);
            goto out;
        }

        if (TEMP_FAILURE_RETRY(lseek(fd, 1024, SEEK_SET)) < 0 ||
            TEMP_FAILURE_RETRY(read(fd, super_buf, 1024)) != 1024) {
            /* Probably a loopback device or something else without a readable
             * superblock.
             */
            close(fd);
            continue;
        }

        sb = (struct ext4_super_block *)super_buf;
        if (sb->s_magic != EXT4_SUPER_MAGIC) {
            INFO("/dev/block/%s not ext{234}\n", ent->d_name);
            continue;
        }

        if (!strncmp(label, sb->s_volume_name, label_len)) {
            char *new_blk_device;

            if (asprintf(&new_blk_device, "/dev/block/%s", ent->d_name) < 0) {
                ERROR("Could not allocate block device string\n");
                goto out;
            }

            INFO("resolved label %s to %s\n", rec->blk_device, new_blk_device);

            free(rec->blk_device);
            rec->blk_device = new_blk_device;
            ret = 0;
            break;
        }
    }

out:
    closedir(blockdir);
    return ret;
}
コード例 #11
0
ファイル: highlight.cpp プロジェクト: fimmtiu/fish-shell
/* Tests whether the specified string cpath is the prefix of anything we could cd to. directories is a list of possible parent directories (typically either the working directory, or the cdpath). This does I/O!

   We expect the path to already be unescaped.
*/
bool is_potential_path(const wcstring &const_path, const wcstring_list_t &directories, path_flags_t flags, wcstring *out_path)
{
    ASSERT_IS_BACKGROUND_THREAD();
    
    const bool require_dir = !! (flags & PATH_REQUIRE_DIR);
    wcstring clean_path;
	int has_magic = 0;
	bool result = false;
    
    wcstring path(const_path);
    if (flags & PATH_EXPAND_TILDE)
        expand_tilde(path);    
    
    //	debug( 1, L"%ls -> %ls ->%ls", path, tilde, unescaped );
    
    for( size_t i=0; i < path.size(); i++)
    {
        wchar_t c = path.at(i);
        switch( c )
        {
            case PROCESS_EXPAND:
            case VARIABLE_EXPAND:
            case VARIABLE_EXPAND_SINGLE:
            case BRACKET_BEGIN:
            case BRACKET_END:
            case BRACKET_SEP:
            case ANY_CHAR:
            case ANY_STRING:
            case ANY_STRING_RECURSIVE:
            {
                has_magic = 1;
                break;		
            }
				
            case INTERNAL_SEPARATOR:
            {
                break;
            }
				
            default:
            {
                clean_path.push_back(c);
                break;
            }
				
        }
        
    }
    
    if( ! has_magic && ! clean_path.empty() )
    {
        /* Don't test the same path multiple times, which can happen if the path is absolute and the CDPATH contains multiple entries */
        std::set<wcstring> checked_paths;
        
        /* Keep a cache of which paths / filesystems are case sensitive */
        case_sensitivity_cache_t case_sensitivity_cache;
        
        for (size_t wd_idx = 0; wd_idx < directories.size() && ! result; wd_idx++) {
            const wcstring &wd = directories.at(wd_idx);
            
            const wcstring abs_path = apply_working_directory(clean_path, wd);
            
            /* Skip this if it's empty or we've already checked it */
            if (abs_path.empty() || checked_paths.count(abs_path))
                continue;
            checked_paths.insert(abs_path);
            
            /* If we end with a slash, then it must be a directory */
            bool must_be_full_dir = abs_path.at(abs_path.size()-1) == L'/';
            if (must_be_full_dir) 
            {
                struct stat buf;
                if (0 == wstat(abs_path, &buf) && S_ISDIR(buf.st_mode)) {
                    result = true;
                    /* Return the path suffix, not the whole absolute path */
                    if (out_path)
                        *out_path = clean_path;
                }
            }
            else
            {
                DIR *dir = NULL;
                
                /* We do not end with a slash; it does not have to be a directory */
                const wcstring dir_name = wdirname(abs_path);
                const wcstring base_name = wbasename(abs_path);
                if (dir_name == L"/" && base_name == L"/")
                {
                    result = true;
                    if (out_path)
                        *out_path = clean_path;
                }
                else if ((dir = wopendir(dir_name))) {
                    // We opened the dir_name; look for a string where the base name prefixes it
                    wcstring ent;
                    
                    // Check if we're case insensitive
                    bool case_insensitive = fs_is_case_insensitive(dir_name, dirfd(dir), case_sensitivity_cache);
                    
                    // Don't ask for the is_dir value unless we care, because it can cause extra filesystem acces */
                    bool is_dir = false;
                    while (wreaddir_resolving(dir, dir_name, ent, require_dir ? &is_dir : NULL))
                    {                    

                        /* Determine which function to call to check for prefixes */
                        bool (*prefix_func)(const wcstring &, const wcstring &);
                        if (case_insensitive) {
                            prefix_func = string_prefixes_string_case_insensitive;
                        } else {
                            prefix_func = string_prefixes_string;
                        }

                        if (prefix_func(base_name, ent) && (! require_dir || is_dir))
                        {
                            result = true;
                            if (out_path) {
                                /* We want to return the path in the same "form" as it was given. Take the given path, get its basename. Append that to the output if the basename actually prefixes the path (which it won't if the given path contains no slashes), and isn't a slash (so we don't duplicate slashes). Then append the directory entry. */
                                
                                out_path->clear();
                                const wcstring path_base = wdirname(const_path);
                                
                                
                                if (prefix_func(path_base, const_path)) {
                                    out_path->append(path_base);
                                    if (! string_suffixes_string(L"/", *out_path))
                                        out_path->push_back(L'/');
                                }
                                out_path->append(ent);
                                /* We actually do want a trailing / for directories, since it makes autosuggestion a bit nicer */
                                if (is_dir)
                                    out_path->push_back(L'/');
                            }
                            break;
                        }
                    }
                    closedir(dir);
                }
            }
        }
    }
    return result;
}
コード例 #12
0
ファイル: store.c プロジェクト: MOBO-OSS/systemd-relative
void log_sample(int sample, struct list_sample_data **ptr) {
        static int vmstat;
        static int schedstat;
        char buf[4096];
        char key[256];
        char val[256];
        char rt[256];
        char wt[256];
        char *m;
        int c;
        int p;
        int mod;
        static int e_fd;
        ssize_t s;
        ssize_t n;
        struct dirent *ent;
        int fd;
        struct list_sample_data *sampledata;
        struct ps_sched_struct *ps_prev = NULL;

        sampledata = *ptr;

        /* all the per-process stuff goes here */
        if (!proc) {
                /* find all processes */
                proc = opendir("/proc");
                if (!proc)
                        return;
                procfd = dirfd(proc);
        } else {
                rewinddir(proc);
        }

        if (!vmstat) {
                /* block stuff */
                vmstat = openat(procfd, "vmstat", O_RDONLY);
                if (vmstat == -1) {
                        log_error("Failed to open /proc/vmstat: %m");
                        exit(EXIT_FAILURE);
                }
        }

        n = pread(vmstat, buf, sizeof(buf) - 1, 0);
        if (n <= 0) {
                close(vmstat);
                return;
        }
        buf[n] = '\0';

        m = buf;
        while (m) {
                if (sscanf(m, "%s %s", key, val) < 2)
                        goto vmstat_next;
                if (streq(key, "pgpgin"))
                        sampledata->blockstat.bi = atoi(val);
                if (streq(key, "pgpgout")) {
                        sampledata->blockstat.bo = atoi(val);
                        break;
                }
vmstat_next:
                m = bufgetline(m);
                if (!m)
                        break;
        }

        if (!schedstat) {
                /* overall CPU utilization */
                schedstat = openat(procfd, "schedstat", O_RDONLY);
                if (schedstat == -1) {
                        log_error("Failed to open /proc/schedstat: %m");
                        exit(EXIT_FAILURE);
                }
        }

        n = pread(schedstat, buf, sizeof(buf) - 1, 0);
        if (n <= 0) {
                close(schedstat);
                return;
        }
        buf[n] = '\0';

        m = buf;
        while (m) {
                if (sscanf(m, "%s %*s %*s %*s %*s %*s %*s %s %s", key, rt, wt) < 3)
                        goto schedstat_next;

                if (strstr(key, "cpu")) {
                        c = atoi((const char*)(key+3));
                        if (c > MAXCPUS)
                                /* Oops, we only have room for MAXCPUS data */
                                break;
                        sampledata->runtime[c] = atoll(rt);
                        sampledata->waittime[c] = atoll(wt);

                        if (c == cpus)
                                cpus = c + 1;
                }
schedstat_next:
                m = bufgetline(m);
                if (!m)
                        break;
        }

        if (arg_entropy) {
                if (!e_fd) {
                        e_fd = openat(procfd, "sys/kernel/random/entropy_avail", O_RDONLY);
                }

                if (e_fd) {
                        n = pread(e_fd, buf, sizeof(buf) - 1, 0);
                        if (n > 0) {
                                buf[n] = '\0';
                                sampledata->entropy_avail = atoi(buf);
                        }
                }
        }

        while ((ent = readdir(proc)) != NULL) {
                char filename[PATH_MAX];
                int pid;
                struct ps_struct *ps;

                if ((ent->d_name[0] < '0') || (ent->d_name[0] > '9'))
                        continue;

                pid = atoi(ent->d_name);

                if (pid >= MAXPIDS)
                        continue;

                ps = ps_first;
                while (ps->next_ps) {
                        ps = ps->next_ps;
                        if (ps->pid == pid)
                                break;
                }

                /* end of our LL? then append a new record */
                if (ps->pid != pid) {
                        _cleanup_fclose_ FILE *st = NULL;
                        char t[32];
                        struct ps_struct *parent;

                        ps->next_ps = new0(struct ps_struct, 1);
                        if (!ps->next_ps) {
                                log_oom();
                                exit (EXIT_FAILURE);
                        }
                        ps = ps->next_ps;
                        ps->pid = pid;

                        ps->sample = new0(struct ps_sched_struct, 1);
                        if (!ps->sample) {
                                log_oom();
                                exit (EXIT_FAILURE);
                        }
                        ps->sample->sampledata = sampledata;

                        pscount++;

                        /* mark our first sample */
                        ps->first = ps->last = ps->sample;
                        ps->sample->runtime = atoll(rt);
                        ps->sample->waittime = atoll(wt);

                        /* get name, start time */
                        if (!ps->sched) {
                                sprintf(filename, "%d/sched", pid);
                                ps->sched = openat(procfd, filename, O_RDONLY);
                                if (ps->sched == -1)
                                        continue;
                        }

                        s = pread(ps->sched, buf, sizeof(buf) - 1, 0);
                        if (s <= 0) {
                                close(ps->sched);
                                continue;
                        }
                        buf[s] = '\0';

                        if (!sscanf(buf, "%s %*s %*s", key))
                                continue;

                        strscpy(ps->name, sizeof(ps->name), key);

                        /* cmdline */
                        if (arg_show_cmdline)
                                pid_cmdline_strscpy(ps->name, sizeof(ps->name), pid);

                        /* discard line 2 */
                        m = bufgetline(buf);
                        if (!m)
                                continue;

                        m = bufgetline(m);
                        if (!m)
                                continue;

                        if (!sscanf(m, "%*s %*s %s", t))
                                continue;

                        ps->starttime = strtod(t, NULL) / 1000.0;

                        /* ppid */
                        sprintf(filename, "%d/stat", pid);
                        fd = openat(procfd, filename, O_RDONLY);
                        st = fdopen(fd, "r");
                        if (!st)
                                continue;
                        if (!fscanf(st, "%*s %*s %*s %i", &p)) {
                                continue;
                        }
                        ps->ppid = p;

                        /*
                         * setup child pointers
                         *
                         * these are used to paint the tree coherently later
                         * each parent has a LL of children, and a LL of siblings
                         */
                        if (pid == 1)
                                continue; /* nothing to do for init atm */

                        /* kthreadd has ppid=0, which breaks our tree ordering */
                        if (ps->ppid == 0)
                                ps->ppid = 1;

                        parent = ps_first;
                        while ((parent->next_ps && parent->pid != ps->ppid))
                                parent = parent->next_ps;

                        if (parent->pid != ps->ppid) {
                                /* orphan */
                                ps->ppid = 1;
                                parent = ps_first->next_ps;
                        }

                        ps->parent = parent;

                        if (!parent->children) {
                                /* it's the first child */
                                parent->children = ps;
                        } else {
                                /* walk all children and append */
                                struct ps_struct *children;
                                children = parent->children;
                                while (children->next)
                                        children = children->next;
                                children->next = ps;
                        }
                }

                /* else -> found pid, append data in ps */

                /* below here is all continuous logging parts - we get here on every
                 * iteration */

                /* rt, wt */
                if (!ps->schedstat) {
                        sprintf(filename, "%d/schedstat", pid);
                        ps->schedstat = openat(procfd, filename, O_RDONLY);
                        if (ps->schedstat == -1)
                                continue;
                }
                s = pread(ps->schedstat, buf, sizeof(buf) - 1, 0);
                if (s <= 0) {
                        /* clean up our file descriptors - assume that the process exited */
                        close(ps->schedstat);
                        if (ps->sched)
                                close(ps->sched);
                        //if (ps->smaps)
                        //        fclose(ps->smaps);
                        continue;
                }
                buf[s] = '\0';

                if (!sscanf(buf, "%s %s %*s", rt, wt))
                        continue;

                ps->sample->next = new0(struct ps_sched_struct, 1);
                if (!ps->sample) {
                        log_oom();
                        exit(EXIT_FAILURE);
                }
                ps->sample->next->prev = ps->sample;
                ps->sample = ps->sample->next;
                ps->last = ps->sample;
                ps->sample->runtime = atoll(rt);
                ps->sample->waittime = atoll(wt);
                ps->sample->sampledata = sampledata;
                ps->sample->ps_new = ps;
                if (ps_prev) {
                        ps_prev->cross = ps->sample;
                }
                ps_prev = ps->sample;
                ps->total = (ps->last->runtime - ps->first->runtime)
                            / 1000000000.0;

                if (!arg_pss)
                        goto catch_rename;

                /* Pss */
                if (!ps->smaps) {
                        sprintf(filename, "%d/smaps", pid);
                        fd = openat(procfd, filename, O_RDONLY);
                        ps->smaps = fdopen(fd, "r");
                        if (!ps->smaps)
                                continue;
                        setvbuf(ps->smaps, smaps_buf, _IOFBF, sizeof(smaps_buf));
                }
                else {
                        rewind(ps->smaps);
                }
                /* test to see if we need to skip another field */
                if (skip == 0) {
                        if (fgets(buf, sizeof(buf), ps->smaps) == NULL) {
                                continue;
                        }
                        if (fread(buf, 1, 28 * 15, ps->smaps) != (28 * 15)) {
                                continue;
                        }
                        if (buf[392] == 'V') {
                                skip = 2;
                        }
                        else {
                                skip = 1;
                        }
                        rewind(ps->smaps);
                }
                while (1) {
                        int pss_kb;

                        /* skip one line, this contains the object mapped. */
                        if (fgets(buf, sizeof(buf), ps->smaps) == NULL) {
                                break;
                        }
                        /* then there's a 28 char 14 line block */
                        if (fread(buf, 1, 28 * 14, ps->smaps) != 28 * 14) {
                                break;
                        }
                        pss_kb = atoi(&buf[61]);
                        ps->sample->pss += pss_kb;

                        /* skip one more line if this is a newer kernel */
                        if (skip == 2) {
                               if (fgets(buf, sizeof(buf), ps->smaps) == NULL)
                                       break;
                        }
                }
                if (ps->sample->pss > ps->pss_max)
                        ps->pss_max = ps->sample->pss;

catch_rename:
                /* catch process rename, try to randomize time */
                mod = (arg_hz < 4.0) ? 4.0 : (arg_hz / 4.0);
                if (((samples - ps->pid) + pid) % (int)(mod) == 0) {

                        /* re-fetch name */
                        /* get name, start time */
                        if (!ps->sched) {
                                sprintf(filename, "%d/sched", pid);
                                ps->sched = openat(procfd, filename, O_RDONLY);
                                if (ps->sched == -1)
                                        continue;
                        }
                        s = pread(ps->sched, buf, sizeof(buf) - 1, 0);
                        if (s <= 0) {
                                /* clean up file descriptors */
                                close(ps->sched);
                                if (ps->schedstat)
                                        close(ps->schedstat);
                                //if (ps->smaps)
                                //        fclose(ps->smaps);
                                continue;
                        }
                        buf[s] = '\0';

                        if (!sscanf(buf, "%s %*s %*s", key))
                                continue;

                        strscpy(ps->name, sizeof(ps->name), key);

                        /* cmdline */
                        if (arg_show_cmdline)
                                pid_cmdline_strscpy(ps->name, sizeof(ps->name), pid);
                }
        }
コード例 #13
0
ファイル: getcwd.c プロジェクト: DanielMSchmidt/it-sec
char *
__getcwd (char *buf, size_t size)
{
  /* Lengths of big file name components and entire file names, and a
     deep level of file name nesting.  These numbers are not upper
     bounds; they are merely large values suitable for initial
     allocations, designed to be large enough for most real-world
     uses.  */
  enum
    {
      BIG_FILE_NAME_COMPONENT_LENGTH = 255,
      BIG_FILE_NAME_LENGTH = MIN (4095, PATH_MAX - 1),
      DEEP_NESTING = 100
    };

#if HAVE_OPENAT_SUPPORT
  int fd = AT_FDCWD;
  bool fd_needs_closing = false;
#else
  char dots[DEEP_NESTING * sizeof ".." + BIG_FILE_NAME_COMPONENT_LENGTH + 1];
  char *dotlist = dots;
  size_t dotsize = sizeof dots;
  size_t dotlen = 0;
#endif
  DIR *dirstream = NULL;
  dev_t rootdev, thisdev;
  ino_t rootino, thisino;
  char *dir;
  register char *dirp;
  struct stat st;
  size_t allocated = size;
  size_t used;

#if HAVE_PARTLY_WORKING_GETCWD
  /* The system getcwd works, except it sometimes fails when it
     shouldn't, setting errno to ERANGE, ENAMETOOLONG, or ENOENT.  If
     AT_FDCWD is not defined, the algorithm below is O(N**2) and this
     is much slower than the system getcwd (at least on GNU/Linux).
     So trust the system getcwd's results unless they look
     suspicious.

     Use the system getcwd even if we have openat support, since the
     system getcwd works even when a parent is unreadable, while the
     openat-based approach does not.  */

# undef getcwd
  dir = getcwd (buf, size);
  if (dir || (errno != ERANGE && errno != ENAMETOOLONG && errno != ENOENT))
    return dir;
#endif

  if (size == 0)
    {
      if (buf != NULL)
        {
          __set_errno (EINVAL);
          return NULL;
        }

      allocated = BIG_FILE_NAME_LENGTH + 1;
    }

  if (buf == NULL)
    {
      dir = malloc (allocated);
      if (dir == NULL)
        return NULL;
    }
  else
    dir = buf;

  dirp = dir + allocated;
  *--dirp = '\0';

  if (__lstat (".", &st) < 0)
    goto lose;
  thisdev = st.st_dev;
  thisino = st.st_ino;

  if (__lstat ("/", &st) < 0)
    goto lose;
  rootdev = st.st_dev;
  rootino = st.st_ino;

  while (!(thisdev == rootdev && thisino == rootino))
    {
      struct dirent *d;
      dev_t dotdev;
      ino_t dotino;
      bool mount_point;
      int parent_status;
      size_t dirroom;
      size_t namlen;
      bool use_d_ino = true;

      /* Look at the parent directory.  */
#if HAVE_OPENAT_SUPPORT
      fd = openat (fd, "..", O_RDONLY);
      if (fd < 0)
        goto lose;
      fd_needs_closing = true;
      parent_status = fstat (fd, &st);
#else
      dotlist[dotlen++] = '.';
      dotlist[dotlen++] = '.';
      dotlist[dotlen] = '\0';
      parent_status = __lstat (dotlist, &st);
#endif
      if (parent_status != 0)
        goto lose;

      if (dirstream && __closedir (dirstream) != 0)
        {
          dirstream = NULL;
          goto lose;
        }

      /* Figure out if this directory is a mount point.  */
      dotdev = st.st_dev;
      dotino = st.st_ino;
      mount_point = dotdev != thisdev;

      /* Search for the last directory.  */
#if HAVE_OPENAT_SUPPORT
      dirstream = fdopendir (fd);
      if (dirstream == NULL)
        goto lose;
      /* Reset fd.  It may have been closed by fdopendir.  */
      fd = dirfd (dirstream);
      fd_needs_closing = false;
#else
      dirstream = __opendir (dotlist);
      if (dirstream == NULL)
        goto lose;
      dotlist[dotlen++] = '/';
#endif
      for (;;)
        {
          /* Clear errno to distinguish EOF from error if readdir returns
             NULL.  */
          __set_errno (0);
          d = __readdir (dirstream);

          /* When we've iterated through all directory entries without finding
             one with a matching d_ino, rewind the stream and consider each
             name again, but this time, using lstat.  This is necessary in a
             chroot on at least one system (glibc-2.3.6 + linux 2.6.12), where
             .., ../.., ../../.., etc. all had the same device number, yet the
             d_ino values for entries in / did not match those obtained
             via lstat.  */
          if (d == NULL && errno == 0 && use_d_ino)
            {
              use_d_ino = false;
              rewinddir (dirstream);
              d = __readdir (dirstream);
            }

          if (d == NULL)
            {
              if (errno == 0)
                /* EOF on dirstream, which can mean e.g., that the current
                   directory has been removed.  */
                __set_errno (ENOENT);
              goto lose;
            }
          if (d->d_name[0] == '.' &&
              (d->d_name[1] == '\0' ||
               (d->d_name[1] == '.' && d->d_name[2] == '\0')))
            continue;

          if (use_d_ino)
            {
              bool match = (MATCHING_INO (d, thisino) || mount_point);
              if (! match)
                continue;
            }

          {
            int entry_status;
#if HAVE_OPENAT_SUPPORT
            entry_status = fstatat (fd, d->d_name, &st, AT_SYMLINK_NOFOLLOW);
#else
            /* Compute size needed for this file name, or for the file
               name ".." in the same directory, whichever is larger.
               Room for ".." might be needed the next time through
               the outer loop.  */
            size_t name_alloc = _D_ALLOC_NAMLEN (d);
            size_t filesize = dotlen + MAX (sizeof "..", name_alloc);

            if (filesize < dotlen)
              goto memory_exhausted;

            if (dotsize < filesize)
              {
                /* My, what a deep directory tree you have, Grandma.  */
                size_t newsize = MAX (filesize, dotsize * 2);
                size_t i;
                if (newsize < dotsize)
                  goto memory_exhausted;
                if (dotlist != dots)
                  free (dotlist);
                dotlist = malloc (newsize);
                if (dotlist == NULL)
                  goto lose;
                dotsize = newsize;

                i = 0;
                do
                  {
                    dotlist[i++] = '.';
                    dotlist[i++] = '.';
                    dotlist[i++] = '/';
                  }
                while (i < dotlen);
              }

            memcpy (dotlist + dotlen, d->d_name, _D_ALLOC_NAMLEN (d));
            entry_status = __lstat (dotlist, &st);
#endif
            /* We don't fail here if we cannot stat() a directory entry.
               This can happen when (network) file systems fail.  If this
               entry is in fact the one we are looking for we will find
               out soon as we reach the end of the directory without
               having found anything.  */
            if (entry_status == 0 && S_ISDIR (st.st_mode)
                && st.st_dev == thisdev && st.st_ino == thisino)
              break;
          }
        }

      dirroom = dirp - dir;
      namlen = _D_EXACT_NAMLEN (d);

      if (dirroom <= namlen)
        {
          if (size != 0)
            {
              __set_errno (ERANGE);
              goto lose;
            }
          else
            {
              char *tmp;
              size_t oldsize = allocated;

              allocated += MAX (allocated, namlen);
              if (allocated < oldsize
                  || ! (tmp = realloc (dir, allocated)))
                goto memory_exhausted;

              /* Move current contents up to the end of the buffer.
                 This is guaranteed to be non-overlapping.  */
              dirp = memcpy (tmp + allocated - (oldsize - dirroom),
                             tmp + dirroom,
                             oldsize - dirroom);
              dir = tmp;
            }
        }
      dirp -= namlen;
      memcpy (dirp, d->d_name, namlen);
      *--dirp = '/';

      thisdev = dotdev;
      thisino = dotino;
    }

  if (dirstream && __closedir (dirstream) != 0)
    {
      dirstream = NULL;
      goto lose;
    }

  if (dirp == &dir[allocated - 1])
    *--dirp = '/';

#if ! HAVE_OPENAT_SUPPORT
  if (dotlist != dots)
    free (dotlist);
#endif

  used = dir + allocated - dirp;
  memmove (dir, dirp, used);

  if (size == 0)
    /* Ensure that the buffer is only as large as necessary.  */
    buf = realloc (dir, used);

  if (buf == NULL)
    /* Either buf was NULL all along, or `realloc' failed but
       we still have the original string.  */
    buf = dir;

  return buf;

 memory_exhausted:
  __set_errno (ENOMEM);
 lose:
  {
    int save = errno;
    if (dirstream)
      __closedir (dirstream);
#if HAVE_OPENAT_SUPPORT
    if (fd_needs_closing)
      close (fd);
#else
    if (dotlist != dots)
      free (dotlist);
#endif
    if (buf == NULL)
      free (dir);
    __set_errno (save);
  }
  return NULL;
}
コード例 #14
0
ファイル: fts_compat.c プロジェクト: 2ion/polipo-patched
int
change_to_dir(DIR *dir)
{
    return fchdir(dirfd(dir));
}
コード例 #15
0
ファイル: procutils.c プロジェクト: babuneelam/util-linux
int proc_next_pid(struct proc_processes *ps, pid_t *pid)
{
	struct dirent *d;

	if (!ps || !pid)
		return -EINVAL;

	*pid = 0;
	errno = 0;

	do {
		char buf[BUFSIZ], *p;

		d = readdir(ps->dir);
		if (!d)
			return errno ? -1 : 1;		/* error or end-of-dir */


		if (!isdigit((unsigned char) *d->d_name))
			continue;

		/* filter out by UID */
		if (ps->has_fltr_uid) {
			struct stat st;

			if (fstat_at(dirfd(ps->dir), "/proc", d->d_name, &st, 0))
				continue;
			if (ps->fltr_uid != st.st_uid)
				continue;
		}

		/* filter out by NAME */
		if (ps->has_fltr_name) {
			char procname[256];
			FILE *f;

			snprintf(buf, sizeof(buf), "%s/stat", d->d_name);
			f = fopen_at(dirfd(ps->dir), "/proc", buf,
						O_CLOEXEC|O_RDONLY, "r");
			if (!f)
				continue;

			p = fgets(buf, sizeof(buf), f);
			fclose(f);

			if (sscanf(buf, "%*d (%255[^)])", procname) != 1)
				continue;

			/* ok, we got the process name. */
			if (strcmp(procname, ps->fltr_name) != 0)
				continue;
		}

		p = NULL;
		errno = 0;
		*pid = (pid_t) strtol(d->d_name, &p, 10);
		if (errno || d->d_name == p || (p && *p))
			return errno ? -errno : -1;

		return 0;
	} while (1);

	return 0;
}
コード例 #16
0
ファイル: PackageSet.cpp プロジェクト: kdt3rd/constructor
void
PackageSet::init( void )
{
	if ( myInit )
		return;
	myInit = true;

	DEBUG( "---------- PackageSet::init --------------" );

	for ( auto &i: myPkgSearchPath )
	{
		// first trim any trailing slashes, win32 opendir doesn't seem to like it
		String::strip( i );
		File::trimTrailingSeparators( i );

		DIR *d = ::opendir( i.c_str() );
		if ( d )
		{
			ON_EXIT{ ::closedir( d ); };
			// glibc deprecates readdir_r in 2.24...
#if defined(__GNU_LIBRARY__) && ( __GLIBC__ > 2 || ( __GLIBC__ == 2 && __GLIBC_MINOR__ >= 24 ) ) 
			while ( true )
			{
				errno = 0;
				struct dirent *cur = ::readdir( d );
				if ( ! cur )
				{
					if ( errno != 0 )
					{
						std::cerr << "WARNING: error reading directory '" << i << "'" << std::endl;
					}
					break;
				}

				std::string cname = cur->d_name;
				std::string::size_type ePC = cname.rfind( ".pc", std::string::npos, 3 );
				if ( ePC != std::string::npos )
				{
					if ( ePC == ( cname.size() - 3 ) )
					{
						std::string name = cname.substr( 0, ePC );
						// if we found the same name earlier, ignore this one
						if ( myPackageConfigs.find( name ) == myPackageConfigs.end() )
						{
							std::string fullpath = i;
							fullpath.push_back( File::pathSeparator() );
							fullpath.append( cname );
							DEBUG( name << ": " << fullpath );
							myPackageConfigs[name] = fullpath;
						}
					}
				}
			}
#else
			std::unique_ptr<uint8_t[]> rdBuf;
			size_t allocSize = 0;
			long name_max = fpathconf( dirfd( d ), _PC_NAME_MAX );
			if ( name_max == -1 )
			{
#if defined(NAME_MAX)
                name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
#else
                name_max = 255;
#endif
			}
			allocSize = sizeof(struct dirent) + static_cast<size_t>( name_max ) + 1;
			rdBuf.reset( new uint8_t[allocSize] );

			struct dirent *curDir = reinterpret_cast<struct dirent *>( rdBuf.get() );
			struct dirent *cur = nullptr;
			while ( readdir_r( d, curDir, &cur ) == 0 )
			{
				if ( ! cur )
					break;

				std::string cname = cur->d_name;
				std::string::size_type ePC = cname.rfind( ".pc", std::string::npos, 3 );
				if ( ePC != std::string::npos )
				{
					if ( ePC == ( cname.size() - 3 ) )
					{
						std::string name = cname.substr( 0, ePC );
						// if we found the same name earlier, ignore this one
						if ( myPackageConfigs.find( name ) == myPackageConfigs.end() )
						{
							std::string fullpath = i;
							fullpath.push_back( File::pathSeparator() );
							fullpath.append( cname );
							myPackageConfigs[name] = fullpath;
						}
					}
				}
			}
#endif
		}
	}
}
コード例 #17
0
ファイル: PackageSet.cpp プロジェクト: iangodin/constructor
void
PackageSet::init( void )
{
	if ( myInit )
		return;
	myInit = true;


	for ( auto &i: myPkgSearchPath )
	{
		// first trim any trailing slashes, win32 opendir doesn't seem to like it
		String::strip( i );
		File::trimTrailingSeparators( i );

		DIR *d = ::opendir( i.c_str() );
		if ( d )
		{
			ON_EXIT{ ::closedir( d ); };

			std::unique_ptr<uint8_t[]> rdBuf;
			size_t allocSize = 0;
			long name_max = fpathconf( dirfd( d ), _PC_NAME_MAX );
			if ( name_max == -1 )
			{
#if defined(NAME_MAX)
                name_max = (NAME_MAX > 255) ? NAME_MAX : 255;
#else
                name_max = 255;
#endif
			}
			allocSize = sizeof(struct dirent) + static_cast<size_t>( name_max ) + 1;
			rdBuf.reset( new uint8_t[allocSize] );

			struct dirent *curDir = reinterpret_cast<struct dirent *>( rdBuf.get() );
			struct dirent *cur = nullptr;
			while ( readdir_r( d, curDir, &cur ) == 0 )
			{
				if ( ! cur )
					break;

				std::string cname = cur->d_name;
				std::string::size_type ePC = cname.rfind( ".pc", std::string::npos, 3 );
				if ( ePC != std::string::npos )
				{
					if ( ePC == ( cname.size() - 3 ) )
					{
						std::string name = cname.substr( 0, ePC );
						// if we found the same name earlier, ignore this one
						if ( myPackageConfigs.find( name ) == myPackageConfigs.end() )
						{
							std::string fullpath = i;
							fullpath.push_back( File::pathSeparator() );
							fullpath.append( cname );
							myPackageConfigs[name] = fullpath;
						}
					}
				}
			}
		}
	}
}
コード例 #18
0
ファイル: mkfs.c プロジェクト: guneetsinghmehta/CS537_OS
int
add_dir(DIR *cur_dir, int cur_inode, int parent_inode) {
	int r;
	int child_inode;
	int cur_fd, child_fd;
	struct xv6_dirent de;
	struct dinode din;
	struct dirent dir_buf;
	struct dirent *entry;
	struct stat st;
	int bytes_read;
	char buf[BLOCK_SIZE];
	int off;

	bzero(&de, sizeof(de));
	de.inum = xshort(cur_inode);
	strcpy(de.name, ".");
	iappend(cur_inode, &de, sizeof(de));

	bzero(&de, sizeof(de));
	de.inum = xshort(parent_inode);
	strcpy(de.name, "..");
	iappend(cur_inode, &de, sizeof(de));

	if (cur_dir == NULL) {
		return 0;
	}

	cur_fd = dirfd(cur_dir);
	if (cur_fd == -1){
		perror("add_dir");
		exit(EXIT_FAILURE);
	}

	if (fchdir(cur_fd) != 0){
		perror("add_dir");
		return -1;
	}

	while (true) {
		r = readdir_r(cur_dir, &dir_buf, &entry);

		if (r != 0) {
			perror("add_dir");
			return -1;
		}

		if (entry == NULL)
			break;

		if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0)
			continue;

		printf("%s\n", entry->d_name);

		child_fd = open(entry->d_name, O_RDONLY);
		if (child_fd == -1) {
			perror("open");
			return -1;
		}

		r = fstat(child_fd, &st);
		if (r != 0) {
			perror("stat");
			return -1;
		}

		if (S_ISDIR(st.st_mode)) {
      child_inode = ialloc(T_DIR);
			r = add_dir(fdopendir(child_fd), child_inode, cur_inode);
			if (r != 0) return r;
			if (fchdir(cur_fd) != 0) {
				perror("chdir");
				return -1;
			}
		} else {
			bytes_read = 0;
	  		child_inode = ialloc(T_FILE);
			bzero(&de, sizeof(de));
			while((bytes_read = read(child_fd, buf, sizeof(buf))) > 0) {
				iappend(child_inode, buf, bytes_read);
			}
		}
		close(child_fd);

		de.inum = xshort(child_inode);
		strncpy(de.name, entry->d_name, DIRSIZ);
		iappend(cur_inode, &de, sizeof(de));

	}

	// fix size of inode cur_dir
	rinode(cur_inode, &din);
	off = xint(din.size);
	off = ((off/BSIZE) + 1) * BSIZE;
	din.size = xint(off);
	winode(cur_inode, &din);
	return 0;
}
コード例 #19
0
ファイル: run.c プロジェクト: 2510/glusterfs
int
runner_start (runner_t *runner)
{
        int pi[3][2] = {{-1, -1}, {-1, -1}, {-1, -1}};
        int xpi[2];
        int ret = 0;
        int errno_priv = 0;
        int i = 0;
        sigset_t set;

        if (runner->runerr) {
                errno = runner->runerr;
                return -1;
        }

        GF_ASSERT (runner->argv[0]);

        /* set up a channel to child to communicate back
         * possible execve(2) failures
         */
        ret = pipe(xpi);
        if (ret != -1)
                ret = fcntl (xpi[1], F_SETFD, FD_CLOEXEC);

        for (i = 0; i < 3; i++) {
                if (runner->chfd[i] != -2)
                        continue;
                ret = pipe (pi[i]);
                if (ret != -1) {
                        runner->chio[i] = fdopen (pi[i][i ? 0 : 1], i ? "r" : "w");
                        if (!runner->chio[i])
                                ret = -1;
                }
        }

        if (ret != -1)
                runner->chpid = fork ();
        switch (runner->chpid) {
        case -1:
                errno_priv = errno;
                sys_close (xpi[0]);
                sys_close (xpi[1]);
                for (i = 0; i < 3; i++) {
                        sys_close (pi[i][0]);
                        sys_close (pi[i][1]);
                }
                errno = errno_priv;
                return -1;
        case 0:
                for (i = 0; i < 3; i++)
                        sys_close (pi[i][i ? 0 : 1]);
                sys_close (xpi[0]);
                ret = 0;

                for (i = 0; i < 3; i++) {
                        if (ret == -1)
                                break;
                        switch (runner->chfd[i]) {
                        case -1:
                                /* no redir */
                                break;
                        case -2:
                                /* redir to pipe */
                                ret = dup2 (pi[i][i ? 1 : 0], i);
                                break;
                        default:
                                /* redir to file */
                                ret = dup2 (runner->chfd[i], i);
                        }
                }

                if (ret != -1 ) {
#ifdef GF_LINUX_HOST_OS
                        DIR *d = NULL;
                        struct dirent *de = NULL;
                        char *e = NULL;

                        d = sys_opendir ("/proc/self/fd");
                        if (d) {
                                while ((de = sys_readdir (d))) {
                                        i = strtoul (de->d_name, &e, 10);
                                        if (*e == '\0' && i > 2 &&
                                            i != dirfd (d) && i != xpi[1])
                                                sys_close (i);
                                }
                                sys_closedir (d);
                        } else
                                ret = -1;
#else /* !GF_LINUX_HOST_OS */
                        struct rlimit rl;
                        ret = getrlimit (RLIMIT_NOFILE, &rl);
                        GF_ASSERT (ret == 0);

                        for (i = 3; i < rl.rlim_cur; i++) {
                                if (i != xpi[1])
                                        sys_close (i);
                        }
#endif /* !GF_LINUX_HOST_OS */
                }

                if (ret != -1) {
                        /* save child from inheriting our singal handling */
                        sigemptyset (&set);
                        sigprocmask (SIG_SETMASK, &set, NULL);

                        execvp (runner->argv[0], runner->argv);
                }
                ret = sys_write (xpi[1], &errno, sizeof (errno));
                _exit (1);
        }

        errno_priv = errno;
        for (i = 0; i < 3; i++)
                sys_close (pi[i][i ? 1 : 0]);
        sys_close (xpi[1]);
        if (ret == -1) {
                for (i = 0; i < 3; i++) {
                        if (runner->chio[i]) {
                                fclose (runner->chio[i]);
                                runner->chio[i] = NULL;
                        }
                }
        } else {
                ret = sys_read (xpi[0], (char *)&errno_priv, sizeof (errno_priv));
                sys_close (xpi[0]);
                if (ret <= 0)
                        return 0;
                GF_ASSERT (ret == sizeof (errno_priv));
        }
        errno = errno_priv;
        return -1;
}
コード例 #20
0
ファイル: init_process.c プロジェクト: B-Rich/chromium
void SystemInitProcess(int init_fd, int child_pid, int proc_fd, int null_fd) {
  int ret = 0;

  // CLONE_NEWPID doesn't adjust the contents of the "/proc" file system.
  // This is very confusing. And it is even possible the kernel developers
  // will consider this a bug and fix it at some point in the future.
  // So, to be on the safe side, we explicitly retrieve our process id
  // from the "/proc" file system. This should continue to work, even if
  // the kernel eventually gets fixed so that "/proc" shows the view from
  // inside of the new pid namespace.
  pid_t init_pid = getProcessStatus(proc_fd, "self", "Pid");
  if (init_pid <= 0) {
    fprintf(stderr,
            "Failed to determine real process id of new \"init\" process\n");
    _exit(1);
  }

  // Redirect stdio to /dev/null
  if (null_fd < 0 ||
      dup2(null_fd, 0) != 0 ||
      dup2(null_fd, 1) != 1 ||
      dup2(null_fd, 2) != 2) {
    fprintf(stderr, "Failed to point stdio to a safe place\n");
    _exit(1);
  }
  close(null_fd);

  // Close all file handles
  int fds_fd = openat(proc_fd, "self/fd", O_RDONLY | O_DIRECTORY);
  DIR *dir = fds_fd >= 0 ? fdopendir(fds_fd) : NULL;
  if (dir == NULL) {
    // If we don't know the list of our open file handles, just try closing
    // all valid ones.
    for (int fd = sysconf(_SC_OPEN_MAX); --fd > 2; ) {
      if (fd != init_fd && fd != proc_fd) {
        close(fd);
      }
    }
  } else {
    // If available, it is much more efficient to just close the file
    // handles that show up in "/proc/self/fd/"
    struct dirent de, *res;
    while (!readdir_r(dir, &de, &res) && res) {
      if (res->d_name[0] < '0')
        continue;
      int fd = atoi(res->d_name);
      if (fd > 2 && fd != init_fd && fd != proc_fd && fd != dirfd(dir)) {
        close(fd);
      }
    }
    closedir(dir);
  }

  // Set up signal handler to catch SIGCHLD, but mask the signal for now
  sigset_t mask;
  sigemptyset(&mask);
  sigaddset(&mask, SIGCHLD);
  sigprocmask(SIG_BLOCK, &mask, NULL);

  // Notify other processes that we are done initializing
  if (write(init_fd, " ", 1)) { }
  close(init_fd);

  // Handle dying processes that have been re-parented to the "init" process
  for (;;) {
    bool retry = false;
    do {
      for (;;) {
        // Reap all exit codes of our child processes. This includes both
        // processes that originally were our immediate children, and processes
        // that have since been re-parented to be our children.
        int status;
        pid_t pid = waitpid(0, &status, __WALL | WNOHANG);
        if (pid <= 0) {
          break;
        } else {
          // We found some newly deceased child processes. Better schedule
          // another very thorough inspection of our state.
          retry = false;
        }
        if (pid == child_pid) {
          // If our first immediate child died, remember its exit code. That's
          // the exit code that we should be reporting to our parent process
          if (WIFEXITED(status)) {
            ret = WEXITSTATUS(status);
          } else if (WIFSIGNALED(status)) {
            ret = -WTERMSIG(status);
          }
        }
      }
      if (hasChildren(proc_fd, init_pid)) {
        // As long as we still have child processes, continue waiting for
        // their ultimate demise.
        retry = false;
      } else {
        if (retry) {
          // No more child processes. We can exit now.
          if (ret < 0) {
            // Try to exit with the same signal that our child terminated with
            signal(-ret, SIG_DFL);
            kill(1, -ret);
            ret = 1;
          }
          // Exit with the same exit code that our child exited with
          _exit(ret);
        } else {
          // There is a little bit of a race condition between getting
          // notifications and scanning the "/proc" file system. This is
          // particularly true, because scanning "/proc" cannot possibly be
          // an atomic operation.
          // If we find that we no longer appear to have any children, we check
          // one more time whether there are any children we can now reap.
          // They might have died while we were scanning "/proc" and if so,
          // they should now show up.
          retry = true;
        }
      }
    } while (retry);

    // Wait until we receive a SIGCHLD signal. Our signal handler doesn't
    // actually need to do anything, though
    sigwaitinfo(&mask, NULL);
  }
}
コード例 #21
0
ファイル: coredump.c プロジェクト: crrodriguez/systemd
/* Joins /proc/[pid]/fd/ and /proc/[pid]/fdinfo/ into the following lines:
 * 0:/dev/pts/23
 * pos:    0
 * flags:  0100002
 *
 * 1:/dev/pts/23
 * pos:    0
 * flags:  0100002
 *
 * 2:/dev/pts/23
 * pos:    0
 * flags:  0100002
 * EOF
 */
static int compose_open_fds(pid_t pid, char **open_fds) {
        _cleanup_closedir_ DIR *proc_fd_dir = NULL;
        _cleanup_close_ int proc_fdinfo_fd = -1;
        _cleanup_free_ char *buffer = NULL;
        _cleanup_fclose_ FILE *stream = NULL;
        const char *fddelim = "", *path;
        struct dirent *dent = NULL;
        size_t size = 0;
        int r = 0;

        assert(pid >= 0);
        assert(open_fds != NULL);

        path = procfs_file_alloca(pid, "fd");
        proc_fd_dir = opendir(path);
        if (!proc_fd_dir)
                return -errno;

        proc_fdinfo_fd = openat(dirfd(proc_fd_dir), "../fdinfo", O_DIRECTORY|O_NOFOLLOW|O_CLOEXEC|O_PATH);
        if (proc_fdinfo_fd < 0)
                return -errno;

        stream = open_memstream(&buffer, &size);
        if (!stream)
                return -ENOMEM;

        FOREACH_DIRENT(dent, proc_fd_dir, return -errno) {
                _cleanup_fclose_ FILE *fdinfo = NULL;
                _cleanup_free_ char *fdname = NULL;
                char line[LINE_MAX];
                int fd;

                r = readlinkat_malloc(dirfd(proc_fd_dir), dent->d_name, &fdname);
                if (r < 0)
                        return r;

                fprintf(stream, "%s%s:%s\n", fddelim, dent->d_name, fdname);
                fddelim = "\n";

                /* Use the directory entry from /proc/[pid]/fd with /proc/[pid]/fdinfo */
                fd = openat(proc_fdinfo_fd, dent->d_name, O_NOFOLLOW|O_CLOEXEC|O_RDONLY);
                if (fd < 0)
                        continue;

                fdinfo = fdopen(fd, "re");
                if (fdinfo == NULL) {
                        close(fd);
                        continue;
                }

                FOREACH_LINE(line, fdinfo, break) {
                        fputs(line, stream);
                        if (!endswith(line, "\n"))
                                fputc('\n', stream);
                }
        }

        errno = 0;
        stream = safe_fclose(stream);

        if (errno > 0)
                return -errno;

        *open_fds = buffer;
        buffer = NULL;

        return 0;
}
コード例 #22
0
ファイル: switch_root.c プロジェクト: gg0/util-linux
/* remove all files/directories below dirName -- don't cross mountpoints */
static int recursiveRemove(int fd)
{
	struct stat rb;
	DIR *dir;
	int rc = -1;
	int dfd;

	if (!(dir = fdopendir(fd))) {
		warn(_("failed to open directory"));
		goto done;
	}

	/* fdopendir() precludes us from continuing to use the input fd */
	dfd = dirfd(dir);

	if (fstat(dfd, &rb)) {
		warn(_("stat failed"));
		goto done;
	}

	while(1) {
		struct dirent *d;
		int isdir = 0;

		errno = 0;
		if (!(d = readdir(dir))) {
			if (errno) {
				warn(_("failed to read directory"));
				goto done;
			}
			break;	/* end of directory */
		}

		if (!strcmp(d->d_name, ".") || !strcmp(d->d_name, ".."))
			continue;
#ifdef _DIRENT_HAVE_D_TYPE
		if (d->d_type == DT_DIR || d->d_type == DT_UNKNOWN)
#endif
		{
			struct stat sb;

			if (fstatat(dfd, d->d_name, &sb, AT_SYMLINK_NOFOLLOW)) {
				warn(_("stat failed %s"), d->d_name);
				continue;
			}

			/* remove subdirectories if device is same as dir */
			if (S_ISDIR(sb.st_mode) && sb.st_dev == rb.st_dev) {
				int cfd;

				cfd = openat(dfd, d->d_name, O_RDONLY);
				if (cfd >= 0) {
					recursiveRemove(cfd);
					close(cfd);
				}
				isdir = 1;
			} else
				continue;
		}

		if (unlinkat(dfd, d->d_name, isdir ? AT_REMOVEDIR : 0))
			warn(_("failed to unlink %s"), d->d_name);
	}

	rc = 0;	/* success */

done:
	if (dir)
		closedir(dir);
	return rc;
}
コード例 #23
0
ファイル: commands.c プロジェクト: AOSPLUS/frameworks_native
int movefiles()
{
    DIR *d;
    int dfd, subfd;
    struct dirent *de;
    struct stat s;
    char buf[PKG_PATH_MAX+1];
    int bufp, bufe, bufi, readlen;

    char srcpkg[PKG_NAME_MAX];
    char dstpkg[PKG_NAME_MAX];
    char srcpath[PKG_PATH_MAX];
    char dstpath[PKG_PATH_MAX];
    int dstuid=-1, dstgid=-1;
    int hasspace;

    d = opendir(UPDATE_COMMANDS_DIR_PREFIX);
    if (d == NULL) {
        goto done;
    }
    dfd = dirfd(d);

        /* Iterate through all files in the directory, executing the
         * file movements requested there-in.
         */
    while ((de = readdir(d))) {
        const char *name = de->d_name;

        if (de->d_type == DT_DIR) {
            continue;
        } else {
            subfd = openat(dfd, name, O_RDONLY);
            if (subfd < 0) {
                ALOGW("Unable to open update commands at %s%s\n",
                        UPDATE_COMMANDS_DIR_PREFIX, name);
                continue;
            }
            
            bufp = 0;
            bufe = 0;
            buf[PKG_PATH_MAX] = 0;
            srcpkg[0] = dstpkg[0] = 0;
            while (1) {
                bufi = bufp;
                while (bufi < bufe && buf[bufi] != '\n') {
                    bufi++;
                }
                if (bufi < bufe) {
                    buf[bufi] = 0;
                    ALOGV("Processing line: %s\n", buf+bufp);
                    hasspace = 0;
                    while (bufp < bufi && isspace(buf[bufp])) {
                        hasspace = 1;
                        bufp++;
                    }
                    if (buf[bufp] == '#' || bufp == bufi) {
                        // skip comments and empty lines.
                    } else if (hasspace) {
                        if (dstpkg[0] == 0) {
                            ALOGW("Path before package line in %s%s: %s\n",
                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
                        } else if (srcpkg[0] == 0) {
                            // Skip -- source package no longer exists.
                        } else {
                            ALOGV("Move file: %s (from %s to %s)\n", buf+bufp, srcpkg, dstpkg);
                            if (!create_move_path(srcpath, srcpkg, buf+bufp, 0) &&
                                    !create_move_path(dstpath, dstpkg, buf+bufp, 0)) {
                                movefileordir(srcpath, dstpath,
                                        strlen(dstpath)-strlen(buf+bufp),
                                        dstuid, dstgid, &s);
                            }
                        }
                    } else {
                        char* div = strchr(buf+bufp, ':');
                        if (div == NULL) {
                            ALOGW("Bad package spec in %s%s; no ':' sep: %s\n",
                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
                        } else {
                            *div = 0;
                            div++;
                            if (strlen(buf+bufp) < PKG_NAME_MAX) {
                                strcpy(dstpkg, buf+bufp);
                            } else {
                                srcpkg[0] = dstpkg[0] = 0;
                                ALOGW("Package name too long in %s%s: %s\n",
                                        UPDATE_COMMANDS_DIR_PREFIX, name, buf+bufp);
                            }
                            if (strlen(div) < PKG_NAME_MAX) {
                                strcpy(srcpkg, div);
                            } else {
                                srcpkg[0] = dstpkg[0] = 0;
                                ALOGW("Package name too long in %s%s: %s\n",
                                        UPDATE_COMMANDS_DIR_PREFIX, name, div);
                            }
                            if (srcpkg[0] != 0) {
                                if (!create_pkg_path(srcpath, srcpkg, PKG_DIR_POSTFIX, 0)) {
                                    if (lstat(srcpath, &s) < 0) {
                                        // Package no longer exists -- skip.
                                        srcpkg[0] = 0;
                                    }
                                } else {
                                    srcpkg[0] = 0;
                                    ALOGW("Can't create path %s in %s%s\n",
                                            div, UPDATE_COMMANDS_DIR_PREFIX, name);
                                }
                                if (srcpkg[0] != 0) {
                                    if (!create_pkg_path(dstpath, dstpkg, PKG_DIR_POSTFIX, 0)) {
                                        if (lstat(dstpath, &s) == 0) {
                                            dstuid = s.st_uid;
                                            dstgid = s.st_gid;
                                        } else {
                                            // Destination package doesn't
                                            // exist...  due to original-package,
                                            // this is normal, so don't be
                                            // noisy about it.
                                            srcpkg[0] = 0;
                                        }
                                    } else {
                                        srcpkg[0] = 0;
                                        ALOGW("Can't create path %s in %s%s\n",
                                                div, UPDATE_COMMANDS_DIR_PREFIX, name);
                                    }
                                }
                                ALOGV("Transfering from %s to %s: uid=%d\n",
                                    srcpkg, dstpkg, dstuid);
                            }
                        }
                    }
                    bufp = bufi+1;
                } else {
                    if (bufp == 0) {
                        if (bufp < bufe) {
                            ALOGW("Line too long in %s%s, skipping: %s\n",
                                    UPDATE_COMMANDS_DIR_PREFIX, name, buf);
                        }
                    } else if (bufp < bufe) {
                        memcpy(buf, buf+bufp, bufe-bufp);
                        bufe -= bufp;
                        bufp = 0;
                    }
                    readlen = read(subfd, buf+bufe, PKG_PATH_MAX-bufe);
                    if (readlen < 0) {
                        ALOGW("Failure reading update commands in %s%s: %s\n",
                                UPDATE_COMMANDS_DIR_PREFIX, name, strerror(errno));
                        break;
                    } else if (readlen == 0) {
                        break;
                    }
                    bufe += readlen;
                    buf[bufe] = 0;
                    ALOGV("Read buf: %s\n", buf);
                }
            }
            close(subfd);
        }
    }
    closedir(d);
done:
    return 0;
}
コード例 #24
0
ファイル: fstest.c プロジェクト: cherry-wb/segvault
static void check_dir(const char *dpath, int level)
{
	DIR *d;
	struct dirent *e;
	char path[PATH_MAX];
	int count = 0, dfd;

	if (level >= 4) {
		puts("excessive recursion detected");
		return;
	}

	// get directory listing
	mlog("+opendir");
	d = opendir(dpath);
	if (d == NULL) {
		printf("opendir failed: %s\n", strerror(errno));
		return;
	}

#if !defined(__NetBSD__)
	// fstatfs
	mlog("+fstatfs");
	dfd = dirfd(d);
	fstatfs(dfd, &sfbuf);
	while ((e = readdir(d))) {
		int rc = -1;

		if (strcmp(e->d_name, ".") == 0)
			continue;
		if (strcmp(e->d_name, "..") == 0)
			continue;

		count++;
		if (count > 64) {
			puts("excessive entries detected");
			break;
		}

		snprintf(path, sizeof(path), "%s/%s", dpath, e->d_name);

		// stat each
		mlog("+stat");
		rc = stat(path, &sbuf);
		if (rc == 0 && S_ISDIR(sbuf.st_mode)) {
			mlog("+chdir");
			if (chdir(path) == 0) {
				mlog("+getcwd");
				getcwd(path, sizeof(path));
				mlog("+fchdir");
				fchdir(dirfd(d));
				chdir(origin);
				check_dir(path, level+1);
			}
		} 
		mlog("+fstatat");
		rc = fstatat(dfd, path, &sbuf, AT_SYMLINK_NOFOLLOW);

		// access each
		mlog("+access");
		access(path, R_OK|W_OK|X_OK);
		mlog("+faccessat");
		faccessat(dfd, path, R_OK|W_OK|X_OK,
			AT_EACCESS|AT_SYMLINK_NOFOLLOW);

		// lstat each
		mlog("+lstat");
		lstat(path, &sbuf);

		// Check xattrs
#ifdef CHECK_XATTR
		mlog("+listxattr");
		listxattr(path, lbuf, MAXLISTBUF);
		mlog("+llistxattr");
		llistxattr(path, lbuf, MAXLISTBUF);
		
		mlog("+getxattr");
		getxattr(path, "selinux", lbuf, MAXLISTBUF);
		mlog("+lgetxattr");
		lgetxattr(path, "selinux", lbuf, MAXLISTBUF);
#endif
		if ( !(S_ISFIFO(sbuf.st_mode)||S_ISSOCK(sbuf.st_mode)) ) {
			int fd;

			mlog("+openat");
			fd = openat(dfd, path, O_RDONLY);
			close(fd);			
			file_read_checks(path);
			mlog("+readlink");
			readlink(path, lbuf, MAXLISTBUF);
			mlog("+readlinkat");
			readlinkat(dfd, path, lbuf, MAXLISTBUF);
		}
	}
#endif
	closedir(d);
}
コード例 #25
0
ファイル: kuserok.c プロジェクト: 2014-class/freerouter
static krb5_error_code
check_directory(krb5_context context, 
		const char *dirname, 
		struct passwd *pwd,
		krb5_principal principal, 
		krb5_boolean *result)
{
    DIR *d;
    struct dirent *dent;
    char filename[MAXPATHLEN];
    krb5_error_code ret = 0;
    struct stat st;

    *result = FALSE;

    if(lstat(dirname, &st) < 0)
	return errno;

    if (!S_ISDIR(st.st_mode))
	return ENOTDIR;
    
    if (st.st_uid != pwd->pw_uid && st.st_uid != 0)
	return EACCES;
    if ((st.st_mode & (S_IWGRP | S_IWOTH)) != 0)
	return EACCES;

    if((d = opendir(dirname)) == NULL) 
	return errno;

#ifdef HAVE_DIRFD
    {
	int fd;
	struct stat st2;

	fd = dirfd(d);
	if(fstat(fd, &st2) < 0) {
	    closedir(d);
	    return errno;
	}
	if(st.st_dev != st2.st_dev || st.st_ino != st2.st_ino) {
	    closedir(d);
	    return EACCES;
	}
    }
#endif

    while((dent = readdir(d)) != NULL) {
	if(strcmp(dent->d_name, ".") == 0 ||
	   strcmp(dent->d_name, "..") == 0 ||
	   dent->d_name[0] == '#' ||			  /* emacs autosave */
	   dent->d_name[strlen(dent->d_name) - 1] == '~') /* emacs backup */
	    continue;
	snprintf(filename, sizeof(filename), "%s/%s", dirname, dent->d_name);
	ret = check_one_file(context, filename, pwd, principal, result);
	if(ret == 0 && *result == TRUE)
	    break;
	ret = 0; /* don't propagate errors upstream */
    }
    closedir(d);
    return ret;
}
コード例 #26
0
ファイル: chideroot.c プロジェクト: abgoyal/pts-mini-gpl
int main(int argc, char **argv) {
  /* TODO: Add functionality to rmdir new_root, possibly create a subdir to
   * hide it from other users.
   */
  const char *new_root;
  const char *env[] = { NULL, NULL };
  int got, i, fd, pid, pid2, pfd[2], status;
  int okc, failc;
  DIR *dir;
  FILE *f;
  char *p, *q;
  struct dirent *dirent;

  /* Parse command-line */
  (void)argc;
  if (argv[1] == NULL) {
    fprintf(stderr, "Usage: %s <new-root> [<command> [<arg>]]\n", argv[0]);
    return 1;
  }
  if (strlen(argv[1]) > sizeof(buf) - 10) {
    fprintf(stderr, "error: name of new_root too long\n");
    return 2;
  }
  new_root = argv[1];

  p = getenv("TERM");
  if (p != NULL) {
    /* TODO: Find it in environ manually, so env_buf is not needed. */
    strcpy(env_buf, "TERM=");
    if (strlen(p) >= sizeof(env_buf) - 5) {
      fprintf(stderr, "error: TERM too long\n");
      return 2;
    }
    strncpy(env_buf + 5, p, sizeof(env_buf) - 5);
    env_buf[sizeof(env_buf) - 1] = '\0';  /* Just for extra safety. */
    env[0] = env_buf;
  }

  fd = open(new_root, O_RDONLY | O_DIRECTORY);  /* Can open a directory. */
  if (fd < 0) {
    perror("open new_root");
    return 2;
  }
  got = umount(new_root);
  if (got == 0) {
    /* Can't succeed, we have fd open. */
    fprintf(stderr, "error: unexpected umount success\n");
    return 2;
  }
  
  if (errno == EINVAL) {
    /* TODO: Detect that new_root is a mount point. */
    fprintf(stderr, "error: new_root is not mounted\n");
    return 2;
  }
  if (errno != EBUSY) {
    perror("umount1");
    return 2;
  }
  close(fd);
  got = pipe(pfd);
  if (got != 0) {
    perror("pipe");
    return 2;
  }
  pid = fork();
  if (pid < 0) {
    perror("fork");
    return 2;
  }
  if (pid == 0) {  /* Child: will umount new_root outside. */
    char c;
    close(pfd[1]);
    got = read(pfd[0], &c, 1);  /* Wait for parent to activate us. */
    if (got != 0) {
      if (got == 0)
        return 0;
      perror("read pfd");
      return 2;
    }
    got = umount(new_root);
    if (got != 0) {
      perror("umount child");
      return 2;
    }
    return 0;
  }
  close(pfd[0]);
  /* umount is needed otherwise the child won't be able to umount new_root.
   * TODO: Umount everything in new_root.
   */
  /* buf is long enough, we've checked that */
  strcpy(buf, new_root);  /* TODO: Use snprintf for extra safety. */
  strcat(buf, "/proc");
  umount(buf);  /* Don't check the result. */

  got = syscall(SYS_unshare, CLONE_NEWNS);
  if (got != 0) {
    perror("unshare");
    return 2;
  }
  got = chdir(new_root);
  if (got != 0) {
    perror("chdir1");
    return 2;
  }
  mkdir("put_old", 0700);  /* Don't check the result. */
    
  got = syscall(SYS_pivot_root, ".", "put_old");
  if (got != 0) {
    /* TODO: Report nice error if put_old is not a directory. */
    /* See restrictions is `man 2 pivot_root' for possible error reasons. */
    perror("pivot_root");
    return 2;
  }
  got = chroot(".");
  if (got != 0) {
    perror("chroot");
    return 2;
  }
  got = chdir("/");
  if (got != 0) {
    perror("chdir2");
    return 2;
  }
  close(pfd[1]);  /* Activate the child, who will umount(new_root). */
  /* Wait for the child to finish the umount. */
  pid2 = waitpid(pid, &status, 0);
  if (pid2 < 0) {
    perror("waitpid");
    return 2;
  }
  if (pid != pid2) {
    fprintf(stderr, "error: unexpected child exit\n");
    return 2;
  }
  if (status != 0) {
    fprintf(stderr, "error: child failed with status=0x%x\n", status);
    return 2;
  }

  umount("/proc");  /* Don't check the result. */
  mkdir("/proc", 0755);  /* Don't check the result. */
  got = mount("none", "/proc", "proc", 0, NULL);
  if (got != 0) {
    perror("mount /proc");
    return 2;
  }

  /* Close all file descriptors other than 0, 1 and 2 (/proc/self/fd). */
  dir = opendir("/proc/self/fd");
  if (dir == NULL) {
    perror("opendir /proc/self/fd");
    return 2;
  }
  fd = dirfd(dir);
  while (NULL != (dirent = readdir(dir))) {
    if (1 == sscanf(dirent->d_name, "%d", &i) && i != fd && i > 2) {
      close(i);  /* Don't check the result. */
    }
  }
  closedir(dir);

  /* Umount all filesystems in put_old. */
  do {
    okc = 0; failc = 0;
    f = fopen("/proc/mounts", "r");
    if (f == NULL) {
      perror("fopen /proc/mounts");
      return 2;
    }
    while (NULL != (p = fgets(buf, sizeof(buf) - 1, f))) {
      if (buf[0] == '\0' || buf[strlen(buf) - 1] != '\n') {
        fprintf(stderr, "error: mounts line empty or too long\n");
        return 2;
      }
      p = buf;
      while (p[0] != '\0' && p[0] != ' ' && p[0] != '\n') {
        ++p;
      }
      while (p[0] == ' ') {
        ++p;
      }
      if (p[0] == '\0' || p[0] == '\n') {
        fprintf(stderr, "error: mounts mount point not found: %s", buf);
        return 2;
      }
      q = p;
      while (q[0] != '\0' && q[0] != ' ') {
        ++q;
      }
      if (q[0] == '\0' || q[0] == '\n') {
        /* No \n. */
        fprintf(stderr, "error: mounts mount point ends: %s", buf);
        return 2;
      }
      q[0] = '\0';
      if (0 == strncmp(p, "/put_old", 8) && (p[8] == '/' || p[8] == '\0')) {
        if (umount(p) != 0) {
          /* It's OK to fail here, because some filesystems are inside
           * each other, and we may try to umount the outer filesystem first.
           */
          /* TODO: Sort by the number of slashes. */
          ++failc;
        } else {
          ++okc;
        }
      }
    }
    if (ferror(f)) {
      fprintf(stderr, "error: reading mounts\n");
      return 2;
    }
    fclose(f);
  } while (okc > 0 && failc > 0);  /* Try to make more progress umounting. */
  if (failc > 0) {
    fprintf(stderr, "error: could not umount put_old\n");
    return 2;
  }

  got = rmdir("/put_old");
  if (got != 0) {
    perror("rmdir put_old");
    return 2;
  }

  if (argv[2] == NULL) {
    got = execle("/bin/sh", "sh", "-i", NULL, env);
  } else {
    got = execve(argv[2], argv + 2, (void*)env);
  }
  if (got != 0) {
    perror("execl");
    return 2;
  }
  return 0;
}
コード例 #27
0
block_t *DirBlock (access_t *p_access)
{
    access_sys_t *p_sys = p_access->p_sys;
    directory_t *current = p_sys->current;

    if (p_access->info.b_eof)
        return NULL;

    if (p_sys->header)
    {   /* Startup: send the XSPF header */
        static const char header[] =
            "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"
            "<playlist version=\"1\" xmlns=\"http://xspf.org/ns/0/\" xmlns:vlc=\"http://www.videolan.org/vlc/playlist/ns/0/\">\n"
            " <trackList>\n";
        block_t *block = block_Alloc (sizeof (header) - 1);
        if (!block)
            goto fatal;
        memcpy (block->p_buffer, header, sizeof (header) - 1);
        p_sys->header = false;
        return block;
    }

    if (current->i >= current->filec)
    {   /* End of directory, go back to parent */
        closedir (current->handle);
        p_sys->current = current->parent;
        free (current->uri);
        free (current->filev);
#ifndef HAVE_OPENAT
        free (current->path);
#endif
        free (current);

        if (p_sys->current == NULL)
        {   /* End of XSPF playlist */
            char *footer;
            int len = asprintf (&footer, " </trackList>\n"
                " <extension application=\"http://www.videolan.org/"
                                             "vlc/playlist/0\">\n"
                "%s"
                " </extension>\n"
                "</playlist>\n", p_sys->xspf_ext ? p_sys->xspf_ext : "");
            if (unlikely(len == -1))
                goto fatal;

            block_t *block = block_heap_Alloc (footer, len);
            p_access->info.b_eof = true;
            return block;
        }
        else
        {
            /* This was the end of a "subnode" */
            /* Write the ID to the extension */
            char *old_xspf_ext = p_sys->xspf_ext;
            if (old_xspf_ext != NULL
             && asprintf (&p_sys->xspf_ext, "%s  </vlc:node>\n",
                          old_xspf_ext ? old_xspf_ext : "") == -1)
                p_sys->xspf_ext = NULL;
            free (old_xspf_ext);
        }
        return NULL;
    }

    char *entry = current->filev[current->i++];

    /* Handle recursion */
    if (p_sys->mode != MODE_COLLAPSE)
    {
        DIR *handle;
#ifdef HAVE_OPENAT
        int fd = vlc_openat (dirfd (current->handle), entry,
                             O_RDONLY | O_DIRECTORY);
        if (fd == -1)
        {
            if (errno == ENOTDIR)
                goto notdir;
            goto skip; /* File cannot be opened... forget it */
        }

        struct stat st;
        if (fstat (fd, &st)
         || p_sys->mode == MODE_NONE
         || has_inode_loop (current, st.st_dev, st.st_ino)
         || (handle = fdopendir (fd)) == NULL)
        {
            close (fd);
            goto skip;
        }
#else
        char *path;
        if (asprintf (&path, "%s/%s", current->path, entry) == -1)
            goto skip;
        if ((handle = vlc_opendir (path)) == NULL)
            goto notdir;
        if (p_sys->mode == MODE_NONE)
            goto skip;
#endif
        directory_t *sub = malloc (sizeof (*sub));
        if (unlikely(sub == NULL))
        {
            closedir (handle);
#ifndef HAVE_OPENAT
            free (path);
#endif
            goto skip;
        }
        sub->parent = current;
        sub->handle = handle;
        sub->filec = vlc_loaddir (handle, &sub->filev, visible, p_sys->compar);
        if (sub->filec < 0)
            sub->filev = NULL;
        sub->i = 0;
#ifdef HAVE_OPENAT
        sub->device = st.st_dev;
        sub->inode = st.st_ino;
#else
        sub->path = path;
#endif
        p_sys->current = sub;

        char *encoded = encode_URI_component (entry);
        if (encoded == NULL
         || (asprintf (&sub->uri, "%s/%s", current->uri, encoded) == -1))
             sub->uri = NULL;
        free (encoded);
        if (unlikely(sub->uri == NULL))
        {
            free (entry);
            goto fatal;
        }

        /* Add node to XSPF extension */
        char *old_xspf_ext = p_sys->xspf_ext;
        EnsureUTF8 (entry);
        char *title = convert_xml_special_chars (entry);
        if (old_xspf_ext != NULL
         && asprintf (&p_sys->xspf_ext, "%s  <vlc:node title=\"%s\">\n",
                      old_xspf_ext, title ? title : "?") == -1)
            p_sys->xspf_ext = NULL;
        free (old_xspf_ext);
        free (title);
        goto skip;
    }

notdir:
    /* Skip files with ignored extensions */
    if (p_sys->ignored_exts != NULL)
    {
        const char *ext = strrchr (entry, '.');
        if (ext != NULL)
        {
            size_t extlen = strlen (++ext);
            for (const char *type = p_sys->ignored_exts, *end;
                 type[0]; type = end + 1)
            {
                end = strchr (type, ',');
                if (end == NULL)
                    end = type + strlen (type);

                if (type + extlen == end
                 && !strncasecmp (ext, type, extlen))
                {
                    free (entry);
                    return NULL;
                }

                if (*end == '\0')
                    break;
            }
        }
    }

    char *encoded = encode_URI_component (entry);
    free (entry);
    if (encoded == NULL)
        goto fatal;
    int len = asprintf (&entry,
                        "  <track><location>%s/%s</location>\n" \
                        "   <extension application=\"http://www.videolan.org/vlc/playlist/0\">\n" \
                        "    <vlc:id>%d</vlc:id>\n" \
                        "   </extension>\n" \
                        "  </track>\n",
                        current->uri, encoded, p_sys->i_item_count++);
    free (encoded);
    if (len == -1)
        goto fatal;

    /* Write the ID to the extension */
    char *old_xspf_ext = p_sys->xspf_ext;
    if (old_xspf_ext != NULL
     && asprintf (&p_sys->xspf_ext, "%s   <vlc:item tid=\"%i\" />\n",
                  old_xspf_ext, p_sys->i_item_count - 1) == -1)
        p_sys->xspf_ext = NULL;
    free (old_xspf_ext);

    block_t *block = block_heap_Alloc (entry, len);
    if (unlikely(block == NULL))
        goto fatal;
    return block;

fatal:
    p_access->info.b_eof = true;
    return NULL;

skip:
    free (entry);
    return NULL;
}
コード例 #28
0
static int clean_posix_shm_internal(DIR *dir, uid_t uid) {
    struct dirent *de;
    int ret = 0, r;

    assert(dir);

    FOREACH_DIRENT(de, dir, goto fail) {
        struct stat st;

        if (STR_IN_SET(de->d_name, "..", "."))
            continue;

        if (fstatat(dirfd(dir), de->d_name, &st, AT_SYMLINK_NOFOLLOW) < 0) {
            if (errno == ENOENT)
                continue;

            log_warning("Failed to stat() POSIX shared memory segment %s: %m", de->d_name);
            ret = -errno;
            continue;
        }

        if (st.st_uid != uid)
            continue;

        if (S_ISDIR(st.st_mode)) {
            _cleanup_closedir_ DIR *kid;

            kid = xopendirat(dirfd(dir), de->d_name, O_NOFOLLOW|O_NOATIME);
            if (!kid) {
                if (errno != ENOENT) {
                    log_warning("Failed to enter shared memory directory %s: %m", de->d_name);
                    ret = -errno;
                }
            } else {
                r = clean_posix_shm_internal(kid, uid);
                if (r < 0)
                    ret = r;
            }

            if (unlinkat(dirfd(dir), de->d_name, AT_REMOVEDIR) < 0) {

                if (errno == ENOENT)
                    continue;

                log_warning("Failed to remove POSIX shared memory directory %s: %m", de->d_name);
                ret = -errno;
            }
        } else {

            if (unlinkat(dirfd(dir), de->d_name, 0) < 0) {

                if (errno == ENOENT)
                    continue;

                log_warning("Failed to remove POSIX shared memory segment %s: %m", de->d_name);
                ret = -errno;
            }
        }
    }

    return ret;

fail:
    log_warning("Failed to read /dev/shm: %m");
    return -errno;
}
コード例 #29
0
ファイル: btrfs-vol.c プロジェクト: DanAnkers/btrfs-progs
int main(int ac, char **av)
{
	struct stat st;
	char *device = NULL;
	char *mnt = NULL;
	int ret;
	int option_index = 0;
	int cmd = 0;
	int fd;
	int devfd = 0;
	DIR *dirstream;
	struct btrfs_ioctl_vol_args args;
	u64 dev_block_count = 0;

	printf( "**\n"
		"** WARNING: this program is considered deprecated\n"
		"** Please consider to switch to the btrfs utility\n"
		"**\n");

	while(1) {
		int c;
		c = getopt_long(ac, av, "a:br:", long_options,
				&option_index);
		if (c < 0)
			break;
		switch(c) {
			case 'a':
				device = strdup(optarg);
				cmd = BTRFS_IOC_ADD_DEV;
				break;
			case 'b':
				cmd = BTRFS_IOC_BALANCE;
				break;
			case 'r':
				device = strdup(optarg);
				cmd = BTRFS_IOC_RM_DEV;
				break;
			default:
				print_usage();
		}
	}
	ac = ac - optind;
	if (ac == 0)
		print_usage();
	mnt = av[optind];

	if (device && strcmp(device, "missing") == 0 &&
	    cmd == BTRFS_IOC_RM_DEV) {
		fprintf(stderr, "removing missing devices from %s\n", mnt);
	} else if (cmd != BTRFS_IOC_BALANCE) {
		if (cmd == BTRFS_IOC_ADD_DEV) {
			ret = check_mounted(device);
			if (ret < 0) {
				fprintf(stderr,
					"error checking %s mount status\n",
					device);
				exit(1);
			}
			if (ret == 1) {
				fprintf(stderr, "%s is mounted\n", device);
				exit(1);
			}
		}
		devfd = open(device, O_RDWR);
		if (devfd < 0) {
			fprintf(stderr, "Unable to open device %s\n", device);
			exit(1);
		}
		ret = fstat(devfd, &st);
		if (ret) {
			fprintf(stderr, "Unable to stat %s\n", device);
			exit(1);
		}
		if (!S_ISBLK(st.st_mode)) {
			fprintf(stderr, "%s is not a block device\n", device);
			exit(1);
		}
	}
	dirstream = opendir(mnt);
	if (!dirstream) {
		fprintf(stderr, "Unable to open directory %s\n", mnt);
		exit(1);
	}
	if (cmd == BTRFS_IOC_ADD_DEV) {
		int mixed = 0;

		ret = btrfs_prepare_device(devfd, device, 1, &dev_block_count, &mixed);
		if (ret) {
			fprintf(stderr, "Unable to init %s\n", device);
			exit(1);
		}
	}
	fd = dirfd(dirstream);
	if (device)
		strcpy(args.name, device);
	else
		args.name[0] = '\0';

	ret = ioctl(fd, cmd, &args);
	printf("ioctl returns %d\n", ret);
	return 0;
}
コード例 #30
0
ファイル: tracker.cpp プロジェクト: basilmon92/coinsparkd
cs_int32 cs_RestoreFromBackUp(cs_int32 *height)
{
    cs_int32 err;
    cs_char folder[CS_DCT_MAX_PATH];
    cs_char subfolder[CS_DCT_MAX_PATH];
    cs_char renamefolder[CS_DCT_MAX_PATH];
    cs_char command[CS_DCT_MAX_PATH];
    cs_char dbname[CS_DCT_MAX_PATH];    
    cs_int32 restore_block,block,dboptions,moved;
    cs_char *ptr;
    cs_char suffix[20];
    
    
    err=CS_ERR_NOERROR;
    
    sprintf(suffix,"%10d",(cs_int32)cs_TimeNow());
    sprintf(folder,"%s%s",g_Args->m_DataDir,CS_DCT_FOLDER_BACKUP);
    
    struct dirent* dent;
    DIR* srcdir = opendir(folder);
    struct stat st;

    restore_block=-1;
    moved=0;
    
    if (srcdir)
    {
        while((dent = readdir(srcdir)) != NULL)
        {
            if((strcmp(dent->d_name, ".") != 0) && (strcmp(dent->d_name, "..") != 0))
            {
                if (fstatat(dirfd(srcdir), dent->d_name, &st, 0) >=0)
                {
                    if (S_ISDIR(st.st_mode))
                    {
                        ptr=dent->d_name;
                        block=0;
                        while(*ptr)
                        {
                            if(block>=0)
                            {
                                if((*ptr>=0x30) && (*ptr<=0x39))
                                {
                                    block=10*block+(*ptr-0x30);
                                }
                                else
                                {
                                    block=-1;
                                }
                            }
                            ptr++;
                        }
                        if(block<*height)
                        {
                            if(block>restore_block)
                            {
                                restore_block=block;
                            }                            
                        }
                        else
                        {
                            sprintf(subfolder,"%s%s%c%06d%c",g_Args->m_DataDir,CS_DCT_FOLDER_BACKUP,CS_DCT_FOLDERSEPARATOR,block,CS_DCT_FOLDERSEPARATOR);
                            sprintf(renamefolder,"%s%s%c%06d-%s%c",g_Args->m_DataDir,CS_DCT_FOLDER_BACKUP,CS_DCT_FOLDERSEPARATOR,block,suffix,CS_DCT_FOLDERSEPARATOR);
                            sprintf(command,"mv %s %s",subfolder,renamefolder);    
                            __US_Shell(command);
                            moved++;
                        }
                    }
                }                
            }
        }
        closedir(srcdir);
    }
 
    strcpy(dbname,g_State->m_AssetDB->m_Name);
    dboptions=g_State->m_AssetDB->m_Options;
    
    g_State->m_AssetDB->Lock(1);
    g_State->m_AssetDB->Close();
    g_State->m_AssetDB->UnLock();
    
    sprintf(renamefolder,"%s%s%cerror-%s%c",g_Args->m_DataDir,CS_DCT_FOLDER_BACKUP,CS_DCT_FOLDERSEPARATOR,suffix,CS_DCT_FOLDERSEPARATOR);
    sprintf(command,"mkdir %s",renamefolder);    
    __US_Shell(command);
    sprintf(command,"mv %s%c* %s",g_Args->m_DataDir,CS_DCT_FOLDERSEPARATOR,renamefolder);    
    __US_Shell(command);

    if(moved)
    {
        sprintf(command,"rm -Rf %s",renamefolder);    
        __US_Shell(command);       
    }

    if(restore_block>=0)
    {
        sprintf(subfolder,"%s%s%c%06d%c",g_Args->m_DataDir,CS_DCT_FOLDER_BACKUP,CS_DCT_FOLDERSEPARATOR,restore_block,CS_DCT_FOLDERSEPARATOR);
        sprintf(command,"cp -Rf %s* %s%c",subfolder,g_Args->m_DataDir,CS_DCT_FOLDERSEPARATOR);    
        __US_Shell(command);        
    }
    
    g_State->m_AssetDB->Lock(1);
    g_State->m_AssetDB->Open(dbname,dboptions);
    g_State->m_AssetDB->UnLock();
    
    *height=restore_block;
    
    return err;
}