1 
2 #include <stdio.h>
3 #include <stdlib.h>
4 #include <string.h>
5 #include <assert.h>
6 
7 #include "compat.h"
8 #include "filelist.h"
9 
10 void insert_entry(struct file_p **, const char *);
11 void destroy_data(void **p);
12 
insert_file(struct file_p ** filep,const char * filename)13 void insert_file(struct file_p **filep, const char *filename) {
14 
15 	struct file_p *behindfile=NULL;
16 
17 #if 0
18 	{
19 		struct file_p *next=*filep;
20 		while (next!=NULL) {
21 			printf("%s (%p %p) data: %p\n", next->filename, next->prevfile,
22 			    next->nextfile, next->data);
23 			next=next->nextfile;
24 		}
25 	}
26 #endif
27 
28 	/* first node and ..-node are inserted at start */
29 	if (*filep==NULL || strcmp(filename, "/..")==0 || strcmp(filename, (*filep)->filename)<0) {
30 		struct file_p *hfile=NULL;
31 
32 		insert_entry(&hfile, filename);
33 		hfile->nextfile=*filep;
34 		if (*filep!=NULL) (*filep)->prevfile=hfile;
35 		*filep=hfile;
36 		return;
37 	}
38 
39 	behindfile = *filep;
40 	while (behindfile->nextfile!=NULL &&
41 	    (strcmp(filename, behindfile->filename)>0 ||
42 	    strcmp(behindfile->filename, "/..")==0)) {
43 		behindfile = behindfile->nextfile;
44 	}
45 
46 	/* scroll one back if less */
47 	if (strcmp(filename, behindfile->filename)<0) {
48 		assert(behindfile->prevfile!=NULL);
49 		behindfile=behindfile->prevfile;
50 	}
51 	insert_entry(&behindfile, filename);
52 }
53 
54 /*
55    This procedure inserts a new entry BEHIND an existing one.
56    If there is no entry (for first entry)
57    */
58 
insert_entry(struct file_p ** filep,const char * filename)59 void insert_entry(struct file_p **filep,const char *filename) {
60 
61 	struct file_p *next;
62 
63 #ifdef VERBOSE
64 	fprintf(stderr,"Inserting element '%s' ", filename);
65 #endif
66 	next=malloc(sizeof(struct file_p));
67 	if (next==NULL) {
68 		fprintf(stderr,"Out of memory.\n");
69 		exit(1);
70 	}
71 	memset(next, 0, sizeof(struct file_p));
72 
73 	strlcpy(next->filename, filename, sizeof(next->filename));
74 	next->data=NULL;
75 
76 	if (*filep==NULL) {
77 		*filep=next;
78 		return;
79 	} else {
80 		/* set pointers in new node */
81 		next->nextfile=(*filep)->nextfile;
82 		next->prevfile=*filep;
83 
84 		/* update predessor */
85 		(*filep)->nextfile=next;
86 
87 		/* update backlink in successor */
88 		if (next->nextfile!=NULL) {
89 			next->nextfile->prevfile=next;
90 		}
91 	}
92 }
93 
seekfirst_file(struct file_p ** filep)94 void seekfirst_file(struct file_p **filep) {
95 	if (*filep==NULL) return;
96 	while ((*filep)->prevfile!=NULL) *filep=(*filep)->prevfile;
97 }
98 
seeklast_file(struct file_p ** filep)99 void seeklast_file(struct file_p **filep) {
100 	if (*filep==NULL) return;
101 	while ((*filep)->nextfile!=NULL) *filep=(*filep)->nextfile;
102 }
103 
delete_all(struct file_p ** filep)104 void delete_all(struct file_p **filep) {
105 
106 	struct file_p *next;
107 
108 #ifdef VERBOSE
109 	fprintf(stderr,"filelist: delete all\n");
110 #endif
111 
112 	seekfirst_file(filep);
113 
114 	while (*filep!=NULL) {
115 		next=(*filep)->nextfile;
116 		destroy_data(&((*filep)->data));
117 		free(*filep);
118 		*filep=next;
119 	}
120 }
121 
delete_all_data(struct file_p * filep)122 void delete_all_data(struct file_p *filep) {
123 
124 #ifdef VERBOSE
125 	fprintf(stderr,"filelist: delete all data\n");
126 #endif
127 
128 	seekfirst_file(&filep);
129 
130 	while (filep!=NULL) {
131 		destroy_data(&(filep->data));
132 		filep=filep->nextfile;
133 	}
134 }
135 
is_file_dir(struct file_p * filep,unsigned int nr)136 int is_file_dir(struct file_p *filep, unsigned int nr) {
137 	char *c;
138 
139 	c=get_file(filep,nr);
140 	if (c==NULL) return 1;
141 
142 	return c[0]=='/' ? 1 : 0;
143 }
144 
get_file(struct file_p * filep,unsigned int nr)145 char *get_file(struct file_p *filep, unsigned int nr) {
146 
147 	unsigned int i=0;
148 
149 #ifdef VERBOSE
150 	fprintf(stderr,"get_file %d ",nr);
151 #endif
152 
153 	for (i=0; i<nr && filep!=NULL; i++, filep=filep->nextfile);
154 
155 #ifdef VERBOSE
156 	fprintf(stderr,"OK '%s'\n",filep==NULL ? "NULL" : filep->filename);
157 #endif
158 	return filep==NULL ? NULL : filep->filename;
159 }
160 
get_data(struct file_p * filep,unsigned int nr)161 void *get_data(struct file_p *filep, unsigned int nr) {
162 
163 	unsigned int i=0;
164 
165 #ifdef VERBOSE
166 	fprintf(stderr,"get_data %d ",nr);
167 #endif
168 	for (i=0; i<nr && filep!=NULL; i++, filep=filep->nextfile);
169 
170 #ifdef VERBOSE
171 	fprintf(stderr,"OK '%s'\n",filep==NULL ? "NULL" : filep->filename);
172 #endif
173 	return filep==NULL ? NULL : filep->data;
174 }
175 
set_data(struct file_p * filep,unsigned int nr,void * data)176 void set_data(struct file_p *filep, unsigned int nr, void *data) {
177 
178 	unsigned int i=0;
179 
180 #ifdef VERBOSE
181 	fprintf(stderr,"set_data %d ",nr);
182 #endif
183 	for (i=0; i<nr && filep!=NULL; i++, filep=filep->nextfile);
184 
185 #ifdef VERBOSE
186 	fprintf(stderr,"OK '%s'\n",filep==NULL ? "NULL" : filep->filename);
187 #endif
188 
189 	if (filep->data!=NULL) printf("filelist warning: Setting data, but "
190 	    "it isn't cleared, yet.");
191 
192 	filep->data=data;
193 }
194