1 /**
2  * @file libcomprex/fsiter.c Filesystem iteration API
3  *
4  * $Id: fsiter.c,v 1.8 2003/01/01 06:22:36 chipx86 Exp $
5  *
6  * @Copyright (C) 2001-2003 The GNUpdate Project.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Library General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Library General Public License for more details.
17  *
18  * You should have received a copy of the GNU Library General Public
19  * License along with this library; if not, write to the
20  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
21  * Boston, MA  02111-1307, USA.
22  */
23 #include <libcomprex/internal.h>
24 
25 static CxFsNode *
__findFirstNode(CxFsNode * baseNode,CxFsNodeType type)26 __findFirstNode(CxFsNode *baseNode, CxFsNodeType type)
27 {
28 	CxFsNode *node;
29 
30 	for (node = baseNode; node != NULL; node = node->next)
31 	{
32 		if (type == CX_FSNODETYPE_UNKNOWN || cxGetFsNodeType(node) == type)
33 			return node;
34 
35 		if (cxGetFsNodeType(node) == CX_FSNODETYPE_DIRECTORY)
36 		{
37 			CxFsNode *tempNode = __findFirstNode(node->u.dir->children, type);
38 
39 			if (tempNode != NULL)
40 				return tempNode;
41 		}
42 	}
43 
44 	return NULL;
45 }
46 
47 static CxFsNode *
__findNextNode(CxFsNode * baseNode,CxFsNodeType type)48 __findNextNode(CxFsNode *baseNode, CxFsNodeType type)
49 {
50 	CxFsNode *node = NULL;
51 
52 	while (baseNode != NULL && node == NULL)
53 	{
54 		if (cxGetFsNodeType(baseNode) == CX_FSNODETYPE_DIRECTORY)
55 			node = baseNode->u.dir->children;
56 
57 		if (node == NULL)
58 			node = cxGetNextFsNode(baseNode);
59 
60 		/* Descend down the directories. */
61 		while (node == NULL && baseNode != NULL)
62 		{
63 			baseNode = cxGetFsNodeParent(baseNode);
64 
65 			if (cxGetNextFsNode(baseNode) != NULL)
66 			{
67 				baseNode = cxGetNextFsNode(baseNode);
68 				node = baseNode;
69 			}
70 		}
71 
72 		if (node != NULL &&
73 			(type == CX_FSNODETYPE_UNKNOWN || cxGetFsNodeType(node) == type))
74 		{
75 			return node;
76 		}
77 		else
78 			node = NULL; /* Continue on. */
79 	}
80 
81 	return NULL;
82 }
83 
84 CxFsIterator *
cxNewFsIterator(CxArchive * archive,CxFsIteratorType type)85 cxNewFsIterator(CxArchive *archive, CxFsIteratorType type)
86 {
87 	CxFsIterator *iterator;
88 
89 	if (archive == NULL)
90 		return NULL;
91 
92 	MEM_CHECK(iterator = (CxFsIterator *)malloc(sizeof(CxFsIterator)));
93 	memset(iterator, 0, sizeof(CxFsIterator));
94 
95 	iterator->type    = type;
96 	iterator->archive = archive;
97 
98 	return iterator;
99 }
100 
101 void
cxDestroyFsIterator(CxFsIterator * iterator)102 cxDestroyFsIterator(CxFsIterator *iterator)
103 {
104 	if (iterator == NULL)
105 		return;
106 
107 	free(iterator);
108 }
109 
110 CxFsNode *
cxGetFsIterFirst(CxFsIterator * iterator)111 cxGetFsIterFirst(CxFsIterator *iterator)
112 {
113 	CxDirectory *root;
114 
115 	if (iterator == NULL)
116 		return NULL;
117 
118 	root = cxGetArchiveRoot(iterator->archive);
119 
120 	if (iterator->type == CX_FSITER_DIRS)
121 	{
122 		iterator->lastNode = __findFirstNode(root->u.dir->children,
123 											CX_FSNODETYPE_DIRECTORY);
124 	}
125 	else if (iterator->type == CX_FSITER_FILES)
126 	{
127 		iterator->lastNode = __findFirstNode(root->u.dir->children,
128 											CX_FSNODETYPE_FILE);
129 	}
130 	else if (iterator->type == CX_FSITER_FILES_DIRS)
131 	{
132 		iterator->lastNode = root->u.dir->children;
133 	}
134 
135 	return iterator->lastNode;
136 }
137 
138 CxFsNode *
cxGetFsIterNext(CxFsIterator * iterator)139 cxGetFsIterNext(CxFsIterator *iterator)
140 {
141 	if (iterator == NULL)
142 		return NULL;
143 
144 	if (iterator->type == CX_FSITER_DIRS)
145 	{
146 		iterator->lastNode = __findNextNode(iterator->lastNode,
147 											CX_FSNODETYPE_DIRECTORY);
148 	}
149 	else if (iterator->type == CX_FSITER_FILES)
150 	{
151 		iterator->lastNode = __findNextNode(iterator->lastNode,
152 											CX_FSNODETYPE_FILE);
153 	}
154 	else if (iterator->type == CX_FSITER_FILES_DIRS)
155 	{
156 		iterator->lastNode = __findNextNode(iterator->lastNode,
157 											CX_FSNODETYPE_UNKNOWN);
158 	}
159 
160 	return iterator->lastNode;
161 }
162 
163 CxFsNode *
cxGetFsIterPrev(CxFsIterator * iterator)164 cxGetFsIterPrev(CxFsIterator *iterator)
165 {
166 	if (iterator == NULL)
167 		return NULL;
168 
169 	return NULL;
170 }
171 
172