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