GCC Code Coverage Report
Directory: ./ Exec Total Coverage
File: lib/libc/gen/seekdir.c Lines: 0 16 0.0 %
Date: 2017-11-07 Branches: 0 16 0.0 %

Line Branch Exec Source
1
/*	$OpenBSD: seekdir.c,v 1.13 2015/09/12 13:34:22 guenther Exp $ */
2
/*
3
 * Copyright (c) 2013 Ingo Schwarze <schwarze@openbsd.org>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
18
#include <dirent.h>
19
#include <unistd.h>
20
21
#include "thread_private.h"
22
#include "telldir.h"
23
24
/*
25
 * Seek to an entry in a directory.
26
 * Only values returned by "telldir" should be passed to seekdir.
27
 */
28
void
29
seekdir(DIR *dirp, long loc)
30
{
31
	struct dirent *dp;
32
33
	/*
34
	 * First check whether the directory entry to seek for
35
	 * is still buffered in the directory structure in memory.
36
	 */
37
38
	_MUTEX_LOCK(&dirp->dd_lock);
39
	if (dirp->dd_size && dirp->dd_bufpos == loc) {
40
		dirp->dd_loc = 0;
41
		dirp->dd_curpos = loc;
42
		_MUTEX_UNLOCK(&dirp->dd_lock);
43
		return;
44
	}
45
46
	for (dirp->dd_loc = 0;
47
	     dirp->dd_loc < dirp->dd_size;
48
	     dirp->dd_loc += dp->d_reclen) {
49
		dp = (struct dirent *)(dirp->dd_buf + dirp->dd_loc);
50
		if (dp->d_off != loc)
51
			continue;
52
53
		/*
54
		 * Entry found in the buffer, use it.  If readdir(3)
55
		 * follows, this will save us a getdents(2) syscall.
56
		 * Note that d_off is the offset of the _next_ entry,
57
		 * so advance dd_loc.
58
		 */
59
60
		dirp->dd_loc += dp->d_reclen;
61
		dirp->dd_curpos = loc;
62
		_MUTEX_UNLOCK(&dirp->dd_lock);
63
		return;
64
	}
65
66
	/*
67
	 * The entry is not in the buffer, prepare a call to getdents(2).
68
	 * In particular, invalidate dd_loc.
69
	 */
70
71
	dirp->dd_loc = dirp->dd_size;
72
	dirp->dd_bufpos = dirp->dd_curpos = lseek(dirp->dd_fd, loc, SEEK_SET);
73
	_MUTEX_UNLOCK(&dirp->dd_lock);
74
}
75
DEF_WEAK(seekdir);