Exemplo n.º 1
0
static NTSTATUS determine_path_error(const char *name,
			bool allow_wcard_last_component)
{
	const char *p;

	if (!allow_wcard_last_component) {
		/* Error code within a pathname. */
		return NT_STATUS_OBJECT_PATH_NOT_FOUND;
	}

	/* We're terminating here so we
	 * can be a little slower and get
	 * the error code right. Windows
	 * treats the last part of the pathname
	 * separately I think, so if the last
	 * component is a wildcard then we treat
	 * this ./ as "end of component" */

	p = strchr(name, '/');

	if (!p && (ms_has_wild(name) || ISDOT(name))) {
		/* Error code at the end of a pathname. */
		return NT_STATUS_OBJECT_NAME_INVALID;
	} else {
		/* Error code within a pathname. */
		return NT_STATUS_OBJECT_PATH_NOT_FOUND;
	}
}
Exemplo n.º 2
0
static void
checkdot(char **argv)
{
	char *p, **save, **t;
	int complained;

	complained = 0;
	for (t = argv; *t;) {
		/* strip trailing slashes */
		p = strrchr(*t, '\0');
		while (--p > *t && *p == '/')
			*p = '\0';

		/* extract basename */
		if ((p = strrchr(*t, '/')) != NULL)
			++p;
		else
			p = *t;

		if (ISDOT(p)) {
			if (!complained++)
				warnx("\".\" and \"..\" may not be removed");
			eval = 1;
			for (save = t; (t[0] = t[1]) != NULL; ++t)
				continue;
			t = save;
		} else
			++t;
	}
}
Exemplo n.º 3
0
static void test_mask(int argc, char *argv[],
					  TALLOC_CTX *mem_ctx,
		      struct smbcli_state *cli)
{
	char *mask, *file;
	int l1, l2, i, l;
	int mc_len = strlen(maskchars);
	int fc_len = strlen(filechars);

	smbcli_mkdir(cli->tree, "\\masktest");

	smbcli_unlink(cli->tree, "\\masktest\\*");

	if (argc >= 2) {
		while (argc >= 2) {
			mask = talloc_strdup(mem_ctx, "\\masktest\\");
			file = talloc_strdup(mem_ctx, "\\masktest\\");
			mask = talloc_strdup_append(mask, argv[0]);
			file = talloc_strdup_append(file, argv[1]);
			testpair(mem_ctx, cli, mask, file);
			argv += 2;
			argc -= 2;
		}
		goto finished;
	}

	while (1) {
		l1 = 1 + random() % max_length;
		l2 = 1 + random() % max_length;
		mask = talloc_strdup(mem_ctx, "\\masktest\\");
		file = talloc_strdup(mem_ctx, "\\masktest\\");
		mask = talloc_realloc_size(mem_ctx, mask, strlen(mask)+l1+1);
		file = talloc_realloc_size(mem_ctx, file, strlen(file)+l2+1);
		l = strlen(mask);
		for (i=0;i<l1;i++) {
			mask[i+l] = maskchars[random() % mc_len];
		}
		mask[l+l1] = 0;

		for (i=0;i<l2;i++) {
			file[i+l] = filechars[random() % fc_len];
		}
		file[l+l2] = 0;

		if (ISDOT(file+l) || ISDOTDOT(file+l) || ISDOTDOT(mask+l)) {
			continue;
		}

		if (strspn(file+l, ".") == strlen(file+l)) continue;

		testpair(mem_ctx, cli, mask, file);
		if (NumLoops && (--NumLoops == 0))
			break;
	}

 finished:
	smbcli_rmdir(cli->tree, "\\masktest");
	talloc_free(mem_ctx);
}
Exemplo n.º 4
0
void
read_cgmem_stats(struct module *mod)
{
    DIR             *dir;
    char            path[128];
    char            line[LEN_128];
    FILE           *memfd;
    struct dirent  *ent;          /* dirent handle */

    n_group = 0;

    memset(cgmem_groups, 0, CGMEM_GROUP_SIZE * MAX_GROUP);
    if ((dir = opendir(CGMEM_PATH)) == NULL) {
        return;
    }

    while ((ent = readdir(dir))) {
        if (ent->d_type == DT_DIR && !ISDOT(ent->d_name)) {  //for each group
            memcpy(&cgmem_groups[n_group].group_name, ent->d_name, strlen(ent->d_name)+1);
            snprintf(path, 128, "%s/%s/memory.stat", CGMEM_PATH, ent->d_name);
            if ((memfd = fopen(path, "r")) == NULL) {
                closedir(dir);
                return;
            }

            while (fgets(line, 128, memfd) != NULL) {
                if (!strncmp(line, "cache", 5)) {
                    sscanf(line + 5, "%lu", &cgmem_groups[n_group].cache);

                } else if (!strncmp(line, "rss", 3)) {
                    sscanf(line + 3, "%lu", &cgmem_groups[n_group].rss);

                } else if (!strncmp(line, "swap", 4)) {
                    sscanf(line + 4, "%lu", &cgmem_groups[n_group].swap);

                } else if (!strncmp(line, "inactive_anon", 13)) {
                    sscanf(line + 13, "%lu", &cgmem_groups[n_group].inanon);

                } else if (!strncmp(line, "active_anon", 11)) {
                    sscanf(line + 11, "%lu", &cgmem_groups[n_group].acanon);

                } else if (!strncmp(line, "inactive_file", 13)) {
                    sscanf(line + 13, "%lu", &cgmem_groups[n_group].infile);

                } else if (!strncmp(line, "active_file", 11)) {
                    sscanf(line + 11, "%lu", &cgmem_groups[n_group].acfile);
                }
            }

            fclose(memfd);
            n_group ++;
        }
    }

    closedir(dir);
    print_cgmem_stats(mod);
}
Exemplo n.º 5
0
int get_real_filename(connection_struct *conn, const char *path,
		      const char *name, TALLOC_CTX *mem_ctx,
		      char **found_name)
{
	struct smb_Dir *cur_dir;
	const char *dname;
	bool mangled;
	char *unmangled_name = NULL;
	long curpos;

	/* open the directory */
	if (!(cur_dir = OpenDir(talloc_tos(), conn, path, NULL, 0))) {
		DEBUG(3,("scan dir didn't open dir [%s]\n",path));
		TALLOC_FREE(unmangled_name);
		return -1;
	}

	/* now scan for matching names */
	curpos = 0;
	while ((dname = ReadDirName(cur_dir, &curpos, NULL))) {

		/* Is it dot or dot dot. */
		if (ISDOT(dname) || ISDOTDOT(dname)) {
			continue;
		}

		/*
		 * At this point dname is the unmangled name.
		 * name is either mangled or not, depending on the state
		 * of the "mangled" variable. JRA.
		 */

		/*
		 * Check mangled name against mangled name, or unmangled name
		 * against unmangled name.
		 */

		if ((mangled && mangled_equal(name,dname,conn->params)) ||
			fname_equal(name, dname, conn->case_sensitive)) {
			/* we've found the file, change it's name and return */
			*found_name = talloc_strdup(mem_ctx, dname);
			TALLOC_FREE(unmangled_name);
			TALLOC_FREE(cur_dir);
			if (!*found_name) {
				errno = ENOMEM;
				return -1;
			}
			return 0;
		}
	}

	TALLOC_FREE(unmangled_name);
	TALLOC_FREE(cur_dir);
	errno = ENOENT;
	return -1;
}
Exemplo n.º 6
0
NTSTATUS can_set_delete_on_close(files_struct *fsp, uint32 dosmode)
{
	/*
	 * Only allow delete on close for writable files.
	 */

	if ((dosmode & FILE_ATTRIBUTE_READONLY) &&
	    !lp_delete_readonly(SNUM(fsp->conn))) {
		DEBUG(10,("can_set_delete_on_close: file %s delete on close "
			  "flag set but file attribute is readonly.\n",
			  fsp_str_dbg(fsp)));
		return NT_STATUS_CANNOT_DELETE;
	}

	/*
	 * Only allow delete on close for writable shares.
	 */

	if (!CAN_WRITE(fsp->conn)) {
		DEBUG(10,("can_set_delete_on_close: file %s delete on "
			  "close flag set but write access denied on share.\n",
			  fsp_str_dbg(fsp)));
		return NT_STATUS_ACCESS_DENIED;
	}

	/*
	 * Only allow delete on close for files/directories opened with delete
	 * intent.
	 */

	if (!(fsp->access_mask & DELETE_ACCESS)) {
		DEBUG(10,("can_set_delete_on_close: file %s delete on "
			  "close flag set but delete access denied.\n",
			  fsp_str_dbg(fsp)));
		return NT_STATUS_ACCESS_DENIED;
	}

	/* Don't allow delete on close for non-empty directories. */
	if (fsp->is_directory) {
		SMB_ASSERT(!is_ntfs_stream_smb_fname(fsp->fsp_name));

		/* Or the root of a share. */
		if (ISDOT(fsp->fsp_name->base_name)) {
			DEBUG(10,("can_set_delete_on_close: can't set delete on "
				  "close for the root of a share.\n"));
			return NT_STATUS_ACCESS_DENIED;
		}

		return can_delete_directory(fsp->conn,
					    fsp->fsp_name->base_name);
	}

	return NT_STATUS_OK;
}
Exemplo n.º 7
0
static bool reg_match_one(struct smbcli_state *cli, const char *pattern, const char *file)
{
	/* oh what a weird world this is */
	if (old_list && strcmp(pattern, "*.*") == 0) return true;

	if (ISDOT(pattern)) return false;

	if (ISDOTDOT(file)) file = ".";

	return ms_fnmatch(pattern, file, cli->transport->negotiate.protocol)==0;
}
Exemplo n.º 8
0
static uint32 set_offline_flag(connection_struct *conn, const char *const path)
{
	if (ISDOT(path) || ISDOTDOT(path)) {
		return 0;
	}

	if (!lp_dmapi_support(SNUM(conn)) || !dmapi_have_session()) {
		return 0;
	}

	return dmapi_file_flags(path);
}
Exemplo n.º 9
0
NTSTATUS check_veto_path(connection_struct *conn, const char *name)
{
	if (IS_VETO_PATH(conn, name))  {
		/* Is it not dot or dot dot. */
		if (!(ISDOT(name) || ISDOTDOT(name))) {
			DEBUG(5,("check_veto_path: file path name %s vetoed\n",
						name));
			return map_nt_error_from_unix(ENOENT);
		}
	}
	return NT_STATUS_OK;
}
Exemplo n.º 10
0
static unsigned short
fts_stat(FTS *sp, FTSENT *p)
{
    FTSENT *t;
    dev_t dev;
    ino_t ino;
    struct stat *sbp;

    /* If user needs stat info, stat buffer already allocated. */
    sbp = p->fts_statp;

    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;

        if (ISDOT(p->fts_name))
            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.
         */
        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);
            }
        return (FTS_D);
    }
    if (S_ISLNK(sbp->st_mode))
        return (FTS_SL);
    if (S_ISREG(sbp->st_mode))
        return (FTS_F);
    return (FTS_DEFAULT);
}
Exemplo n.º 11
0
/*
  seek to the given name
*/
NTSTATUS pvfs_list_seek(struct pvfs_dir *dir, const char *name, off_t *ofs)
{
	struct dirent *de;
	int i;

	dir->end_of_search = False;

	if (ISDOT(name)) {
		dir->offset = DIR_OFFSET_DOTDOT;
		*ofs = dir->offset;
		return NT_STATUS_OK;
	}

	if (ISDOTDOT(name)) {
		dir->offset = DIR_OFFSET_BASE;
		*ofs = dir->offset;
		return NT_STATUS_OK;
	}

	for (i=dir->name_cache_index;i>=0;i--) {
		struct name_cache_entry *e = &dir->name_cache[i];
		if (e->name && strcasecmp_m(name, e->name) == 0) {
			*ofs = e->offset;
			return NT_STATUS_OK;
		}
	}
	for (i=NAME_CACHE_SIZE-1;i>dir->name_cache_index;i--) {
		struct name_cache_entry *e = &dir->name_cache[i];
		if (e->name && strcasecmp_m(name, e->name) == 0) {
			*ofs = e->offset;
			return NT_STATUS_OK;
		}
	}

	rewinddir(dir->dir);

	while ((de = readdir(dir->dir))) {
		if (strcasecmp_m(name, de->d_name) == 0) {
			dir->offset = telldir(dir->dir) + DIR_OFFSET_BASE;
			*ofs = dir->offset;
			return NT_STATUS_OK;
		}
	}

	dir->end_of_search = True;

	return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
Exemplo n.º 12
0
static void listfn(struct clilist_file_info *f, const char *s, void *state)
{
	struct masktest_state *m = (struct masktest_state *)state;

	if (ISDOT(f->name)) {
		resultp[0] = '+';
	} else if (ISDOTDOT(f->name)) {
		resultp[1] = '+';
	} else {
		resultp[2] = '+';
	}

	last_hit.long_name = talloc_strdup(m->mem_ctx, f->name);
	last_hit.short_name = talloc_strdup(m->mem_ctx, f->short_name);
	f_info_hit = true;
}
Exemplo n.º 13
0
/*
  see if a directory is empty
*/
BOOL pvfs_directory_empty(struct pvfs_state *pvfs, struct pvfs_filename *name)
{
	struct dirent *de;
	DIR *dir = opendir(name->full_name);
	if (dir == NULL) {
		return True;
	}

	while ((de = readdir(dir))) {
		if (!ISDOT(de->d_name) && !ISDOTDOT(de->d_name)) {
			closedir(dir);
			return False;
		}
	}

	closedir(dir);
	return True;
}
Exemplo n.º 14
0
/* 
   callback function for torture_deltree() 
*/
static void delete_fn(struct clilist_file_info *finfo, const char *name, void *state)
{
	struct delete_state *dstate = (struct delete_state *)state;
	char *s, *n;
	if (ISDOT(finfo->name) || ISDOTDOT(finfo->name)) {
		return;
	}

	n = strdup(name);
	n[strlen(n)-1] = 0;
	asprintf(&s, "%s%s", n, finfo->name);

	if (finfo->attrib & FILE_ATTRIBUTE_READONLY) {
		if (NT_STATUS_IS_ERR(smbcli_setatr(dstate->tree, s, 0, 0))) {
			DEBUG(2,("Failed to remove READONLY on %s - %s\n",
				 s, smbcli_errstr(dstate->tree)));			
		}
	}

	if (finfo->attrib & FILE_ATTRIBUTE_DIRECTORY) {
		char *s2;
		asprintf(&s2, "%s\\*", s);
		smbcli_unlink(dstate->tree, s2);
		smbcli_list(dstate->tree, s2, 
			 FILE_ATTRIBUTE_DIRECTORY|FILE_ATTRIBUTE_HIDDEN|FILE_ATTRIBUTE_SYSTEM, 
			 delete_fn, state);
		free(s2);
		if (NT_STATUS_IS_ERR(smbcli_rmdir(dstate->tree, s))) {
			DEBUG(2,("Failed to delete %s - %s\n", 
				 s, smbcli_errstr(dstate->tree)));
			dstate->failed = true;
		}
		dstate->total_deleted++;
	} else {
		if (NT_STATUS_IS_ERR(smbcli_unlink(dstate->tree, s))) {
			DEBUG(2,("Failed to delete %s - %s\n", 
				 s, smbcli_errstr(dstate->tree)));
			dstate->failed = true;
		}
		dstate->total_deleted++;
	}
	free(s);
	free(n);
}
Exemplo n.º 15
0
static void gen_name(char *name)
{
	const char *chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz._-$~...";
	uint_t max_idx = strlen(chars);
	uint_t len;
	int i;
	char *p;

	fstrcpy(name, "\\mangle_test\\");
	p = name + strlen(name);

	len = 1 + random() % NAME_LENGTH;
	
	for (i=0;i<len;i++) {
		p[i] = chars[random() % max_idx];
	}

	p[i] = 0;

	if (ISDOT(p) || ISDOTDOT(p)) {
		p[0] = '_';
	}

	/* have a high probability of a common lead char */
	if (random() % 2 == 0) {
		p[0] = 'A';
	}

	/* and a medium probability of a common lead string */
	if (random() % 10 == 0) {
		strncpy(p, "ABCDE", 5);
	}

	/* and a high probability of a good extension length */
	if (random() % 2 == 0) {
		char *s = strrchr(p, '.');
		if (s) {
			s[4] = 0;
		}
	}
}
Exemplo n.º 16
0
checkdot(char **argv)
#endif
{
	char *p, **save, **t;
	int complained;

	complained = 0;
	for (t = argv; *t;) {
		if ((p = strrchr(*t, '/')) != NULL)
			++p;
		else
			p = *t;
		if (ISDOT(p)) {
			if (!complained++)
				warnx("\".\" and \"..\" may not be removed");
			eval = 1;
			for (save = t; (t[0] = t[1]) != NULL; ++t);
			t = save;
		} else
			++t;
	}
}
Exemplo n.º 17
0
void
checkdot(char **argv)
{
	char *p, **save, **t;
	int complained;
	struct stat sb, root;

	stat("/", &root);
	complained = 0;
	for (t = argv; *t;) {
		if (lstat(*t, &sb) == 0 &&
		    root.st_ino == sb.st_ino && root.st_dev == sb.st_dev) {
			if (!complained++)
				warnx("\"/\" may not be removed");
			goto skip;
		}
		/* strip trailing slashes */
		p = strrchr(*t, '\0');
		while (--p > *t && *p == '/')
			*p = '\0';

		/* extract basename */
		if ((p = strrchr(*t, '/')) != NULL)
			++p;
		else
			p = *t;

		if (ISDOT(p)) {
			if (!complained++)
				warnx("\".\" and \"..\" may not be removed");
skip:
			eval = 1;
			for (save = t; (t[0] = t[1]) != NULL; ++t)
				continue;
			t = save;
		} else
			++t;
	}
}
Exemplo n.º 18
0
Arquivo: rm.c Projeto: dezelin/kBuild
static void
checkdot(char **argv)
{
	char *p, **save, **t;
	int complained;

	complained = 0;
	for (t = argv; *t;) {
#ifdef HAVE_DOS_PATHS
		const char *tmp = p = *t;
		while (*tmp) {
			switch (*tmp) {
			case '/':
			case '\\':
			case ':':
				p = (char *)tmp + 1;
				break;
			}
			tmp++;
		}
#else
		if ((p = strrchr(*t, '/')) != NULL)
			++p;
		else
			p = *t;
#endif
		if (ISDOT(p)) {
			if (!complained++)
				fprintf(stderr, "%s: \".\" and \"..\" may not be removed\n", argv0);
			eval = 1;
			for (save = t; (t[0] = t[1]) != NULL; ++t)
				continue;
			t = save;
		} else
			++t;
	}
}
Exemplo n.º 19
0
/*
  recursively delete a directory tree
*/
static void recursive_delete(const char *path)
{
	DIR *dir;
	struct dirent *de;

	dir = opendir(path);
	if (!dir) {
		return;
	}

	for (de=readdir(dir);de;de=readdir(dir)) {
		char *fname;
		struct stat st;

		if (ISDOT(de->d_name) || ISDOTDOT(de->d_name)) {
			continue;
		}

		fname = talloc_asprintf(path, "%s/%s", path, de->d_name);
		if (stat(fname, &st) != 0) {
			continue;
		}
		if (S_ISDIR(st.st_mode)) {
			recursive_delete(fname);
			talloc_free(fname);
			continue;
		}
		if (unlink(fname) != 0) {
			DEBUG(0,("Unabled to delete '%s' - %s\n", 
				 fname, strerror(errno)));
			smb_panic("unable to cleanup tmp files");
		}
		talloc_free(fname);
	}
	closedir(dir);
}
Exemplo n.º 20
0
/**
 * Obtain list of init functions from the modules in the specified
 * directory
 */
static init_module_fn *load_modules(TALLOC_CTX *mem_ctx, const char *path)
{
	DIR *dir;
	struct dirent *entry;
	char *filename;
	int success = 0;
	init_module_fn *ret = talloc_array(mem_ctx, init_module_fn, 2);

	ret[0] = NULL;

	dir = opendir(path);
	if (dir == NULL) {
		talloc_free(ret);
		return NULL;
	}

	while((entry = readdir(dir))) {
		if (ISDOT(entry->d_name) || ISDOTDOT(entry->d_name))
			continue;

		filename = talloc_asprintf(mem_ctx, "%s/%s", path, entry->d_name);

		ret[success] = load_module(filename, true, NULL);
		if (ret[success]) {
			ret = talloc_realloc(mem_ctx, ret, init_module_fn, success+2);
			success++;
			ret[success] = NULL;
		}

		talloc_free(filename);
	}

	closedir(dir);

	return ret;
}
Exemplo n.º 21
0
bool recursive_rmdir(TALLOC_CTX *ctx,
		     connection_struct *conn,
		     struct smb_filename *smb_dname)
{
	const char *dname = NULL;
	char *talloced = NULL;
	bool ret = True;
	long offset = 0;
	SMB_STRUCT_STAT st;
	struct smb_Dir *dir_hnd;

	SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));

	dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
	if(dir_hnd == NULL)
		return False;

	while((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
		struct smb_filename *smb_dname_full = NULL;
		char *fullname = NULL;
		bool do_break = true;

		if (ISDOT(dname) || ISDOTDOT(dname)) {
			TALLOC_FREE(talloced);
			continue;
		}

		if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
				     false)) {
			TALLOC_FREE(talloced);
			continue;
		}

		/* Construct the full name. */
		fullname = talloc_asprintf(ctx,
				"%s/%s",
				smb_dname->base_name,
				dname);
		if (!fullname) {
			errno = ENOMEM;
			goto err_break;
		}

		smb_dname_full = synthetic_smb_fname(talloc_tos(), fullname,
						     NULL, NULL);
		if (smb_dname_full == NULL) {
			errno = ENOMEM;
			goto err_break;
		}

		if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
			goto err_break;
		}

		if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
			if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
				goto err_break;
			}
			if(SMB_VFS_RMDIR(conn,
					 smb_dname_full->base_name) != 0) {
				goto err_break;
			}
		} else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
			goto err_break;
		}

		/* Successful iteration. */
		do_break = false;

	 err_break:
		TALLOC_FREE(smb_dname_full);
		TALLOC_FREE(fullname);
		TALLOC_FREE(talloced);
		if (do_break) {
			ret = false;
			break;
		}
	}
	TALLOC_FREE(dir_hnd);
	return ret;
}
Exemplo n.º 22
0
/*
 * 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 fts_children
 * and fts_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;
	FTSENT *cur, *tail;
	DIR *dirp;
	void *oldaddr;
	size_t len, maxlen;
	int nitems, cderrno, descend, level, nlinks, nostat, doadjust;
	int saved_errno;
	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 fts_read, set the fts_info field.
	 */
	if ((dirp = opendir(cur->fts_accpath)) == NULL) {
		if (type == BREAD) {
			cur->fts_info = FTS_DNR;
			cur->fts_errno = errno;
		}
		return (NULL);
	}

	/*
	 * 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;
	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: %u)\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 fts_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) {
		if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
			if (nlinks && type == BREAD)
				cur->fts_errno = errno;
			cur->fts_flags |= FTS_DONTCHDIR;
			descend = 0;
			cderrno = errno;
			(void)closedir(dirp);
			dirp = NULL;
		} 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 fts_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++ = '/';
	}
	len++;
	maxlen = sp->fts_pathlen - len;

	/*
	 * fts_level is signed so we must prevent it from wrapping
	 * around to FTS_ROOTLEVEL and FTS_ROOTPARENTLEVEL.
	 */
	level = cur->fts_level;
	if (level < FTS_MAXLEVEL)
	    level++;

	/* Read the directory, attaching each entry to the `link' pointer. */
	doadjust = 0;
	for (head = tail = NULL, nitems = 0; dirp && (dp = readdir(dirp));) {
		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
			continue;

		if (!(p = fts_alloc(sp, dp->d_name, (size_t)dp->d_namlen)))
			goto mem1;
		if (dp->d_namlen >= maxlen) {	/* include space for NUL */
			oldaddr = sp->fts_path;
			if (fts_palloc(sp, dp->d_namlen +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);
				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;
		}

		p->fts_level = level;
		p->fts_parent = sp->fts_cur;
		p->fts_pathlen = len + dp->d_namlen;
		if (p->fts_pathlen < len) {
			/*
			 * If we wrap, free up the current structure and
			 * the structures already allocated, then error
			 * out with ENAMETOOLONG.
			 */
			free(p);
			fts_lfree(head);
			(void)closedir(dirp);
			cur->fts_info = FTS_ERR;
			SET(FTS_STOP);
			errno = ENAMETOOLONG;
			return (NULL);
		}

		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(cp, p->fts_name, 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);

	/*
	 * 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, head);

	/*
	 * 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 fts_children or after called from
	 * fts_read and nothing found, get back.  At the root level we use
	 * the saved fd; if one of fts_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);
}
Exemplo n.º 23
0
static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
{
	connection_struct *conn = fsp->conn;
	struct smb_filename *smb_dname = fsp->fsp_name;
	int ret;

	SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));

	/* Might be a symlink. */
	if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
		return map_nt_error_from_unix(errno);
	}

	if (S_ISLNK(smb_dname->st.st_ex_mode)) {
		/* Is what it points to a directory ? */
		if(SMB_VFS_STAT(conn, smb_dname) != 0) {
			return map_nt_error_from_unix(errno);
		}
		if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
			return NT_STATUS_NOT_A_DIRECTORY;
		}
		ret = SMB_VFS_UNLINK(conn, smb_dname);
	} else {
		ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
	}
	if (ret == 0) {
		notify_fname(conn, NOTIFY_ACTION_REMOVED,
			     FILE_NOTIFY_CHANGE_DIR_NAME,
			     smb_dname->base_name);
		return NT_STATUS_OK;
	}

	if(((errno == ENOTEMPTY)||(errno == EEXIST)) && *lp_veto_files(talloc_tos(), SNUM(conn))) {
		/*
		 * Check to see if the only thing in this directory are
		 * vetoed files/directories. If so then delete them and
		 * retry. If we fail to delete any of them (and we *don't*
		 * do a recursive delete) then fail the rmdir.
		 */
		SMB_STRUCT_STAT st;
		const char *dname = NULL;
		char *talloced = NULL;
		long dirpos = 0;
		struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
						  smb_dname->base_name, NULL,
						  0);

		if(dir_hnd == NULL) {
			errno = ENOTEMPTY;
			goto err;
		}

		while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
					    &talloced)) != NULL) {
			if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
				TALLOC_FREE(talloced);
				continue;
			}
			if (!is_visible_file(conn, smb_dname->base_name, dname,
					     &st, false)) {
				TALLOC_FREE(talloced);
				continue;
			}
			if(!IS_VETO_PATH(conn, dname)) {
				TALLOC_FREE(dir_hnd);
				TALLOC_FREE(talloced);
				errno = ENOTEMPTY;
				goto err;
			}
			TALLOC_FREE(talloced);
		}

		/* We only have veto files/directories.
		 * Are we allowed to delete them ? */

		if(!lp_delete_veto_files(SNUM(conn))) {
			TALLOC_FREE(dir_hnd);
			errno = ENOTEMPTY;
			goto err;
		}

		/* Do a recursive delete. */
		RewindDir(dir_hnd,&dirpos);
		while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
					    &talloced)) != NULL) {
			struct smb_filename *smb_dname_full = NULL;
			char *fullname = NULL;
			bool do_break = true;

			if (ISDOT(dname) || ISDOTDOT(dname)) {
				TALLOC_FREE(talloced);
				continue;
			}
			if (!is_visible_file(conn, smb_dname->base_name, dname,
					     &st, false)) {
				TALLOC_FREE(talloced);
				continue;
			}

			fullname = talloc_asprintf(ctx,
					"%s/%s",
					smb_dname->base_name,
					dname);

			if(!fullname) {
				errno = ENOMEM;
				goto err_break;
			}

			smb_dname_full = synthetic_smb_fname(
				talloc_tos(), fullname, NULL, NULL);
			if (smb_dname_full == NULL) {
				errno = ENOMEM;
				goto err_break;
			}

			if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
				goto err_break;
			}
			if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
				if(!recursive_rmdir(ctx, conn,
						    smb_dname_full)) {
					goto err_break;
				}
				if(SMB_VFS_RMDIR(conn,
					smb_dname_full->base_name) != 0) {
					goto err_break;
				}
			} else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
				goto err_break;
			}

			/* Successful iteration. */
			do_break = false;

		 err_break:
			TALLOC_FREE(fullname);
			TALLOC_FREE(smb_dname_full);
			TALLOC_FREE(talloced);
			if (do_break)
				break;
		}
		TALLOC_FREE(dir_hnd);
		/* Retry the rmdir */
		ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
	}

  err:

	if (ret != 0) {
		DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
			 "%s\n", smb_fname_str_dbg(smb_dname),
			 strerror(errno)));
		return map_nt_error_from_unix(errno);
	}

	notify_fname(conn, NOTIFY_ACTION_REMOVED,
		     FILE_NOTIFY_CHANGE_DIR_NAME,
		     smb_dname->base_name);

	return NT_STATUS_OK;
}
Exemplo n.º 24
0
internal_function
fts_build (FTSOBJ *sp, int type)
{
	struct dirent *dp;
	FTSENTRY *p, *head;
	int nitems;
	FTSENTRY *cur, *tail;
	DIR *dirp;
	void *oldaddr;
	int cderrno, descend, len, level, nlinks, saved_errno,
	    nostat, doadjust;
	size_t maxlen;
	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 fts_read, set the fts_info field.
	 */
#if defined FTS_WHITEOUT && 0
	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);
	}

	/*
	 * 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 fts_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) {
		if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
			if (nlinks && type == BREAD)
				cur->fts_errno = errno;
			cur->fts_flags |= FTS_DONTCHDIR;
			descend = 0;
			cderrno = errno;
			(void)__closedir(dirp);
			dirp = NULL;
		} 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 fts_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++ = '/';
	} 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;
	for (head = tail = NULL, nitems = 0; dirp && (dp = __readdir(dirp));) {
		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
			continue;

		if ((p = fts_alloc(sp, dp->d_name, _D_EXACT_NAMLEN (dp))) == NULL)
			goto mem1;
		if (_D_EXACT_NAMLEN (dp) >= maxlen) {/* include space for NUL */
			oldaddr = sp->fts_path;
			if (fts_palloc(sp, _D_EXACT_NAMLEN (dp) + 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;
				free(p);
				fts_lfree(head);
				(void)__closedir(dirp);
				cur->fts_info = FTS_ERR;
				SET(FTS_STOP);
				__set_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 + _D_EXACT_NAMLEN (dp) >= 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);
			cur->fts_info = FTS_ERR;
			SET(FTS_STOP);
			__set_errno (ENAMETOOLONG);
			return (NULL);
		}
		p->fts_level = level;
		p->fts_parent = sp->fts_cur;
		p->fts_pathlen = len + _D_EXACT_NAMLEN (dp);

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

		/* Unreachable code.  cderrno is only ever set to a nonnull
		   value if dirp is closed at the same time.  But then we
		   cannot enter this loop.  */
		if (0 && 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
                           || (nostat && dirent_not_directory(dp))) {
			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(cp, p->fts_name, 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);

	/*
	 * 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, head);

	/*
	 * 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 fts_children or after called from
	 * fts_read and nothing found, get back.  At the root level we use
	 * the saved fd; if one of fts_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);
		fts_lfree(head);
		return (NULL);
	}

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

	/* Sort the entries. */
	if (sp->fts_compar && nitems > 1)
		head = fts_sort(sp, head, nitems);
	return (head);
}
Exemplo n.º 25
0
void
read_cgblkio_stats(struct module *mod)
{
    DIR               *dir;
    char               path[128], buffer[128];
    FILE              *iofd;
    struct dirent     *ent;          /* dirent handle */
    struct blkio_info  curr;

    n_group = 0;

    memset(blkio_groups, 0, CGBLKIO_GROUP_SIZE * MAX_GROUP);
    if ((dir = opendir(CGBLKIO_PATH)) == NULL) {
        return;
    }

    while ((ent = readdir(dir))) {
        if (ent->d_type == DT_DIR && !ISDOT(ent->d_name)) {
            memcpy(&blkio_groups[n_group].group_name, ent->d_name, strlen(ent->d_name) + 1);

            snprintf(path, 128, "%s/%s/blkio.io_merged", CGBLKIO_PATH, ent->d_name);
            if ((iofd = fopen(path, "r")) == NULL) {
                closedir(dir);
                return;
            }
            while (fgets(buffer, 128, iofd) != NULL) {
                if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
                    if (!strncmp(curr.type, "Read", 4))
                        blkio_groups[n_group].rd_merges += curr.num;
                    if (!strncmp(curr.type, "Write", 5))
                        blkio_groups[n_group].wr_merges += curr.num;
                }
            }
            if (fclose(iofd) < 0) {
                return;
            }

            snprintf(path, 128, "%s/%s/blkio.io_serviced", CGBLKIO_PATH, ent->d_name);
            if ((iofd = fopen(path, "r")) == NULL) {
                closedir(dir);
                return;
            }
            while (fgets(buffer, 128, iofd) != NULL) {
                if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
                    if (!strncmp(curr.type, "Read", 4))
                        blkio_groups[n_group].rd_ios += curr.num;
                    if (!strncmp(curr.type, "Write", 5))
                        blkio_groups[n_group].wr_ios += curr.num;
                }
            }
            if (fclose(iofd) < 0) {
                return;
            }

            snprintf(path, 128, "%s/%s/blkio.io_service_bytes", CGBLKIO_PATH, ent->d_name);
            if ((iofd = fopen(path, "r")) == NULL) {
                closedir(dir);
                return;
            }
            while (fgets(buffer, 128, iofd) != NULL) {
                if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
                    if (!strncmp(curr.type, "Read", 4))
                        blkio_groups[n_group].rd_secs += curr.num / SECTOR_SIZE;
                    if (!strncmp(curr.type, "Write", 5))
                        blkio_groups[n_group].wr_secs += curr.num / SECTOR_SIZE;
                }
            }
            if (fclose(iofd) < 0) {
                return;
            }

            snprintf(path, 128, "%s/%s/blkio.io_queued", CGBLKIO_PATH, ent->d_name);
            if ((iofd = fopen(path, "r")) == NULL) {
                closedir(dir);
                return;
            }
            while (fgets(buffer, 128, iofd) != NULL) {
                if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
                    if (!strncmp(curr.type, "Read", 4))
                        blkio_groups[n_group].qusize += curr.num;
                    if (!strncmp(curr.type, "Write", 5))
                        blkio_groups[n_group].qusize += curr.num;
                }
            }
            if (fclose(iofd) < 0) {
                return;
            }

            snprintf(path, 128, "%s/%s/blkio.io_service_time", CGBLKIO_PATH, ent->d_name);
            if ((iofd = fopen(path, "r")) == NULL) {
                closedir(dir);
                return;
            }
            while (fgets(buffer, 128, iofd) != NULL) {
                if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
                    if (!strncmp(curr.type, "Read", 4))
                        blkio_groups[n_group].svctm += (unsigned long long)(curr.num / 1000000); //in ms
                    if (!strncmp(curr.type, "Write", 5))
                        blkio_groups[n_group].svctm += (unsigned long long )(curr.num / 1000000);
                }
            }
            if (fclose(iofd) < 0) {
                return;
            }

            snprintf(path, 128, "%s/%s/blkio.io_wait_time", CGBLKIO_PATH, ent->d_name);
            if ((iofd = fopen(path, "r")) == NULL) {
                closedir(dir);
                return;
            }
            while (fgets(buffer, 128, iofd) != NULL) {
                if (sscanf(buffer, "%s %s %llu", curr.disk, curr.type, &curr.num) == 3) {
                    if (!strncmp(curr.type, "Read", 4))
                        blkio_groups[n_group].wait += (unsigned long long)(curr.num / 1000000);
                    if (!strncmp(curr.type, "Write", 5))
                        blkio_groups[n_group].wait += (unsigned long long)(curr.num / 1000000);
                }
            }
            if (fclose(iofd) < 0) {
                return;
            }

            n_group ++;
        }
    }

    closedir(dir);
    print_cgblkio_stats(mod);
}
Exemplo n.º 26
0
char *
getcwd(char *pt, size_t size)
{
    struct dirent *dp;
    DIR *dir = NULL;
    dev_t dev;
    ino_t ino;
    int first;
    char *bpt, *bup;
    struct stat s;
    dev_t root_dev;
    ino_t root_ino;
    size_t ptsize, upsize;
    int save_errno;
    char *ept, *eup, *up;

    /*
     * If no buffer specified by the user, allocate one as necessary.
     * If a buffer is specified, the size has to be non-zero.  The path
     * is built from the end of the buffer backwards.
     */
    if (pt) {
        ptsize = 0;
        if (!size) {
            errno = EINVAL;
            return (NULL);
        }
        ept = pt + size;
    } else {
        if ((pt = malloc(ptsize = MAXPATHLEN)) == NULL)
            return (NULL);
        ept = pt + ptsize;
    }
    bpt = ept - 1;
    *bpt = '\0';

    /*
     * Allocate bytes for the string of "../"'s.
     * Should always be enough (it's 340 levels).  If it's not, allocate
     * as necessary.  Special * case the first stat, it's ".", not "..".
     */
    if ((up = malloc(upsize = MAXPATHLEN)) == NULL)
        goto err;
    eup = up + upsize;
    bup = up;
    up[0] = '.';
    up[1] = '\0';

    /* Save root values, so know when to stop. */
    if (stat("/", &s))
        goto err;
    root_dev = s.st_dev;
    root_ino = s.st_ino;

    errno = 0;			/* XXX readdir has no error return. */

    for (first = 1;; first = 0) {
        /* Stat the current level. */
        if (lstat(up, &s))
            goto err;

        /* Save current node values. */
        ino = s.st_ino;
        dev = s.st_dev;

        /* Check for reaching root. */
        if (root_dev == dev && root_ino == ino) {
            *--bpt = '/';
            /*
             * It's unclear that it's a requirement to copy the
             * path to the beginning of the buffer, but it's always
             * been that way and stuff would probably break.
             */
            memmove(pt, bpt, ept - bpt);
            free(up);
            return (pt);
        }

        /*
         * Build pointer to the parent directory, allocating memory
         * as necessary.  Max length is 3 for "../", the largest
         * possible component name, plus a trailing NUL.
         */
        if (bup + 3  + MAXNAMLEN + 1 >= eup) {
            char *nup;

            if ((nup = realloc(up, upsize *= 2)) == NULL)
                goto err;
            bup = nup + (bup - up);
            up = nup;
            eup = up + upsize;
        }
        *bup++ = '.';
        *bup++ = '.';
        *bup = '\0';

        /* Open and stat parent directory. */
        if (!(dir = opendir(up)) || fstat(dirfd(dir), &s))
            goto err;

        /* Add trailing slash for next directory. */
        *bup++ = '/';

        /*
         * If it's a mount point, have to stat each element because
         * the inode number in the directory is for the entry in the
         * parent directory, not the inode number of the mounted file.
         */
        save_errno = 0;
        if (s.st_dev == dev) {
            for (;;) {
                if (!(dp = readdir(dir)))
                    goto notfound;
                if (dp->d_fileno == ino)
                    break;
            }
        } else
            for (;;) {
                if (!(dp = readdir(dir)))
                    goto notfound;
                if (ISDOT(dp))
                    continue;
                memcpy(bup, dp->d_name, dp->d_namlen + 1);

                /* Save the first error for later. */
                if (lstat(up, &s)) {
                    if (!save_errno)
                        save_errno = errno;
                    errno = 0;
                    continue;
                }
                if (s.st_dev == dev && s.st_ino == ino)
                    break;
            }

        /*
         * Check for length of the current name, preceding slash,
         * leading slash.
         */
        if (bpt - pt < dp->d_namlen + (first ? 1 : 2)) {
            size_t len;
            char *npt;

            if (!ptsize) {
                errno = ERANGE;
                goto err;
            }
            len = ept - bpt;
            if ((npt = realloc(pt, ptsize *= 2)) == NULL)
                goto err;
            bpt = npt + (bpt - pt);
            pt = npt;
            ept = pt + ptsize;
            memmove(ept - len, bpt, len);
            bpt = ept - len;
        }
        if (!first)
            *--bpt = '/';
        bpt -= dp->d_namlen;
        memcpy(bpt, dp->d_name, dp->d_namlen);
        (void)closedir(dir);

        /* Truncate any file name. */
        *bup = '\0';
    }

notfound:
    /*
     * If readdir set errno, use it, not any saved error; otherwise,
     * didn't find the current directory in its parent directory, set
     * errno to ENOENT.
     */
    if (!errno)
        errno = save_errno ? save_errno : ENOENT;
    /* FALLTHROUGH */
err:
    save_errno = errno;

    if (ptsize)
        free(pt);
    free(up);
    if (dir)
        (void)closedir(dir);

    errno = save_errno;

    return (NULL);
}
Exemplo n.º 27
0
/*
  delete a file - the dirtype specifies the file types to include in the search. 
  The name can contain CIFS wildcards, but rarely does (except with OS/2 clients)
*/
NTSTATUS pvfs_unlink(struct ntvfs_module_context *ntvfs,
		     struct ntvfs_request *req,
		     union smb_unlink *unl)
{
	struct pvfs_state *pvfs = talloc_get_type(ntvfs->private_data,
				  struct pvfs_state);
	struct pvfs_dir *dir;
	NTSTATUS status;
	uint32_t total_deleted=0;
	struct pvfs_filename *name;
	const char *fname;
	off_t ofs;

	/* resolve the cifs name to a posix name */
	status = pvfs_resolve_name(pvfs, req, unl->unlink.in.pattern, 
				   PVFS_RESOLVE_WILDCARD |
				   PVFS_RESOLVE_STREAMS |
				   PVFS_RESOLVE_NO_OPENDB,
				   &name);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	if (!name->exists && !name->has_wildcard) {
		return NT_STATUS_OBJECT_NAME_NOT_FOUND;
	}

	if (name->exists && 
	    (name->dos.attrib & FILE_ATTRIBUTE_DIRECTORY)) {
		return NT_STATUS_FILE_IS_A_DIRECTORY;
	}

	if (!name->has_wildcard) {
		return pvfs_unlink_one(pvfs, req, unl, name);
	}

	/*
	 * disable async requests in the wildcard case
	 * untill we have proper tests for this
	 */
	req->async_states->state &= ~NTVFS_ASYNC_STATE_MAY_ASYNC;

	/* get list of matching files */
	status = pvfs_list_start(pvfs, name, req, &dir);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	status = NT_STATUS_NO_SUCH_FILE;
	talloc_free(name);

	ofs = 0;

	while ((fname = pvfs_list_next(dir, &ofs))) {
		/* this seems to be a special case */
		if ((unl->unlink.in.attrib & FILE_ATTRIBUTE_DIRECTORY) &&
		    (ISDOT(fname) || ISDOTDOT(fname))) {
			return NT_STATUS_OBJECT_NAME_INVALID;
		}

		/* get a pvfs_filename object */
		status = pvfs_resolve_partial(pvfs, req,
					      pvfs_list_unix_path(dir),
					      fname,
					      PVFS_RESOLVE_NO_OPENDB,
					      &name);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}

		status = pvfs_unlink_one(pvfs, req, unl, name);
		if (NT_STATUS_IS_OK(status)) {
			total_deleted++;
		}

		talloc_free(name);
	}

	if (total_deleted > 0) {
		status = NT_STATUS_OK;
	}

	return status;
}
Exemplo n.º 28
0
/*
 * 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);
}
Exemplo n.º 29
0
static u_short
internal_function
fts_stat (FTSOBJ *sp, FTSENTRY *p, int follow)
{
	FTSENTRY *t;
	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;

#if defined FTS_WHITEOUT && 0
	/* 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)) {
				__set_errno (0);
				return (FTS_SLNONE);
			}
			p->fts_errno = saved_errno;
			goto err;
		}
	} else if (LSTAT(p->fts_accpath, sbp)) {
		p->fts_errno = errno;
err:		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;

		if (ISDOT(p->fts_name))
			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.
		 */
		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);
			}
		return (FTS_D);
	}
	if (S_ISLNK(sbp->st_mode))
		return (FTS_SL);
	if (S_ISREG(sbp->st_mode))
		return (FTS_F);
	return (FTS_DEFAULT);
}
Exemplo n.º 30
0
/* 
 * call back action function for dent_walk
 */
static uint8_t
print_dent_act(FS_INFO * fs, FS_DENT * fs_dent, int flags, void *ptr)
{

    /* only print dirs if FLS_DIR is set and only print everything
     ** else if FLS_FILE is set (or we aren't sure what it is)
     */
    if (((localflags & FLS_DIR) &&
	    ((fs_dent->fsi) &&
		((fs_dent->fsi->mode & FS_INODE_FMT) == FS_INODE_DIR))) ||
	((localflags & FLS_FILE) &&
	    (((fs_dent->fsi) &&
		    ((fs_dent->fsi->mode & FS_INODE_FMT) != FS_INODE_DIR))
		|| (!fs_dent->fsi)))) {


	/* Make a special case for NTFS so we can identify all of the
	 * alternate data streams!
	 */
	if (((fs->ftype & FSMASK) == NTFS_TYPE) && (fs_dent->fsi)) {

	    FS_DATA *fs_data = fs_dent->fsi->attr;
	    uint8_t printed = 0;

	    while ((fs_data) && (fs_data->flags & FS_DATA_INUSE)) {

		if (fs_data->type == NTFS_ATYPE_DATA) {
		    mode_t mode = fs_dent->fsi->mode;
		    uint8_t ent_type = fs_dent->ent_type;

		    printed = 1;


		    /* 
		     * A directory can have a Data stream, in which
		     * case it would be printed with modes of a
		     * directory, although it is really a file
		     * So, to avoid confusion we will set the modes
		     * to a file so it is printed that way.  The
		     * entry for the directory itself will still be
		     * printed as a directory
		     */

		    if ((fs_dent->fsi->mode & FS_INODE_FMT) ==
			FS_INODE_DIR) {


			/* we don't want to print the ..:blah stream if
			 * the -a flag was not given
			 */
			if ((fs_dent->name[0] == '.') && (fs_dent->name[1])
			    && (fs_dent->name[2] == '\0') &&
			    ((localflags & FLS_DOT) == 0)) {
			    fs_data = fs_data->next;
			    continue;
			}

			fs_dent->fsi->mode &= ~FS_INODE_FMT;
			fs_dent->fsi->mode |= FS_INODE_REG;
			fs_dent->ent_type = FS_DENT_REG;
		    }

		    printit(fs, fs_dent, flags, fs_data);

		    fs_dent->fsi->mode = mode;
		    fs_dent->ent_type = ent_type;
		}
		else if (fs_data->type == NTFS_ATYPE_IDXROOT) {
		    printed = 1;

		    /* If it is . or .. only print it if the flags say so,
		     * we continue with other streams though in case the 
		     * directory has a data stream 
		     */
		    if (!((ISDOT(fs_dent->name)) &&
			    ((localflags & FLS_DOT) == 0)))
			printit(fs, fs_dent, flags, fs_data);
		}

		fs_data = fs_data->next;
	    }

	    /* A user reported that an allocated file had the standard
	     * attributes, but no $Data.  We should print something */
	    if (printed == 0) {
		printit(fs, fs_dent, flags, NULL);
	    }

	}
	else {
	    /* skip it if it is . or .. and we don't want them */
	    if (!((ISDOT(fs_dent->name)) && ((localflags & FLS_DOT) == 0)))
		printit(fs, fs_dent, flags, NULL);
	}
    }
    return WALK_CONT;
}