1 /*
2 OWFS -- One-Wire filesystem
3 OWHTTPD -- One-Wire Web Server
4 Written 2003 Paul H Alfille
5 email: paul.alfille@gmail.com
6 Released under the GPL
7 See the header file: ow.h for full attribution
8 1wire/iButton system from Dallas Semiconductor
9 */
10
11 /* ow_opt -- owlib specific command line options processing */
12
13
14 #include <config.h>
15 #include "owfs_config.h"
16 #include "ow.h"
17
ReadAliasFile(const ASCII * file)18 GOOD_OR_BAD ReadAliasFile(const ASCII * file)
19 {
20 FILE *alias_file_pointer ;
21
22 /* getline parameters. allocated and reallocated by getline. use free rather than owfree */
23 char * alias_line = NULL ;
24 size_t alias_line_length ;
25 int line_number = 0;
26
27 /* try to open file for reading */
28 alias_file_pointer = fopen(file, "r");
29 if ( alias_file_pointer == NULL ) {
30 ERROR_DEFAULT("Cannot process alias file %s", file);
31 return gbBAD;
32 }
33
34 /* read each line and parse */
35 while (getline(&alias_line, &alias_line_length, alias_file_pointer) >= 0) {
36 ++line_number;
37 BYTE sn[SERIAL_NUMBER_SIZE] ;
38 char * a_line = alias_line ; // pointer within the line
39 char * sn_char = NULL ; // pointer to serial number
40 char * name_char = NULL ; // pointer to alias name
41
42 while ( a_line ) {
43 sn_char = strsep( &a_line, "/ \t=\n");
44 if ( strlen(sn_char)>0 ) {
45 // non delim char
46 break ;
47 }
48 }
49
50 if ( Parse_SerialNumber(sn_char, sn) != sn_valid ) {
51 LEVEL_CALL("Problem parsing device name in alias file %s:%d",file,line_number) ;
52 continue ;
53 }
54
55 if ( a_line ) {
56 a_line += strspn(a_line," \t=") ;
57 }
58 while ( a_line ) {
59 name_char = strsep( &a_line, "\n");
60 size_t len = strlen(name_char) ;
61 if ( len > 0 ) {
62 while ( len>0 ) {
63 if ( name_char[len-1] != ' ' && name_char[len-1] != '\t' ) {
64 break ;
65 }
66 name_char[--len] = '\0' ;
67 }
68 Test_and_Add_Alias( name_char, sn) ;
69 break ;
70 }
71 }
72 }
73 if ( alias_line != NULL ) {
74 free(alias_line) ; // not owfree since allocated by getline
75 }
76 fclose(alias_file_pointer);
77 return gbGOOD;
78 }
79
80 /* Name is a null-terminated string */
81 /* sn is an 8-byte serial number */
82 /* 1. Trims name
83 * 2. Checks name length
84 * 3. Refuses reserved words
85 * 4. Refuses path separator (/)
86 * 5. Removes any old assignments to name or serial number
87 * 6. Add new alias
88 * */
Test_and_Add_Alias(char * name,BYTE * sn)89 GOOD_OR_BAD Test_and_Add_Alias( char * name, BYTE * sn )
90 {
91 BYTE sn_stored[SERIAL_NUMBER_SIZE] ;
92 size_t len ;
93
94 // Parse off initial spaces
95 while ( name[0] == ' ' ) {
96 ++name ;
97 }
98
99 // parse off trailing spaces
100 for ( len = strlen(name) ; len > 0 && name[len-1]==' ' ; ) {
101 -- len ;
102 name[len] = '\0' ;
103 }
104
105 // zero length allowed -- will delete this entry.
106
107 // Check length
108 if ( len > PROPERTY_LENGTH_ALIAS ) {
109 LEVEL_CALL("Alias too long: sn=" SNformat ", Alias=%s, Length=%d, Max length=%d", SNvar(sn), name, (int) len, PROPERTY_LENGTH_ALIAS ) ;
110 return gbBAD ;
111 }
112
113 // Reserved word?
114 if ( strcmp( name, "interface" )==0
115 || strcmp( name, "settings" )==0
116 || strcmp( name, "uncached" )==0
117 || strcmp( name, "unaliased" )==0
118 || strcmp( name, "text" )==0
119 || strcmp( name, "alarm" )==0
120 || strcmp( name, "statistics" )==0
121 || strcmp( name, "simultaneous" )==0
122 || strcmp( name, "structure" )==0
123 || strncmp( name, "bus.", 4 )==0
124 ) {
125 LEVEL_CALL("Alias attempts to redefine reserved filename: %s",name ) ;
126 return gbBAD ;
127 }
128
129 // No path separator allowed in name
130 if ( strchr( name, '/' ) ) {
131 LEVEL_CALL("Alias contains confusing path separator \'/\': %s",name ) ;
132 return gbBAD ;
133 }
134
135 // Is there another assignment for this alias name already?
136 if ( GOOD( Cache_Get_Alias_SN( name, sn_stored ) ) ) {
137 if ( memcmp( sn, sn_stored, SERIAL_NUMBER_SIZE ) == 0 ) {
138 // repeat assignment
139 return gbGOOD ;
140 }
141 // delete old serial number
142 LEVEL_CALL("Alias %s reassigned from "SNformat" to "SNformat,name,SNvar(sn_stored),SNvar(sn)) ;
143 Cache_Del_Alias(sn_stored) ;
144 }
145
146 // Delete any prior assignments for this serial number
147 Cache_Del_Alias(sn) ;
148
149 // Now add
150 return Cache_Add_Alias( name, sn) ;
151 }
152
FS_dir_entry_aliased(void (* dirfunc)(void *,const struct parsedname *),void * v,const struct parsedname * pn)153 void FS_dir_entry_aliased(void (*dirfunc) (void *, const struct parsedname *), void *v, const struct parsedname *pn)
154 {
155 if ( ( pn->state & ePS_unaliased ) == 0 ) {
156 // Want alias substituted
157 struct parsedname s_pn_copy ;
158 struct parsedname * pn_copy = & s_pn_copy ;
159
160 ASCII path[PATH_MAX+3] ;
161 ASCII * path_pointer = path ; // current location in original path
162
163 // Shallow copy
164 memcpy( pn_copy, pn, sizeof(struct parsedname) ) ;
165 pn_copy->path[0] = '\0' ;
166
167 // path copy to use for separation
168 strcpy( path, pn->path ) ;
169
170 // copy segments of path (delimitted by "/") to copy
171 while( path_pointer != NULL ) {
172 ASCII * path_segment = strsep( &path_pointer, "/" ) ;
173 BYTE sn[SERIAL_NUMBER_SIZE] ;
174
175 if ( PATH_MAX < strlen(pn_copy->path) + strlen(path_segment) ) {
176 // too long, just use initial copy
177 strcpy( pn_copy->path, pn->path ) ;
178 break ;
179 }
180
181 //test this segment for serial number
182 if ( Parse_SerialNumber(path_segment,sn) == sn_valid ) {
183 //printf("We see serial number in path "SNformat"\n",SNvar(sn)) ;
184 // now test for alias
185 ASCII * name = Cache_Get_Alias( sn ) ;
186 if ( name != NULL ) {
187 //printf("It's aliased to %s\n",name);
188 // now test for room
189 if ( PATH_MAX < strlen(pn_copy->path) + strlen(name) ) {
190 // too long, just use initial copy
191 strcpy( pn_copy->path, pn->path ) ;
192 owfree(name) ;
193 break ;
194 }
195 // overwrite serial number with alias name
196 strcat( pn_copy->path, name ) ;
197 owfree( name ) ;
198 } else {
199 strcat( pn_copy->path, path_segment ) ;
200 }
201 } else {
202 strcat( pn_copy->path, path_segment ) ;
203 }
204
205 if ( path_pointer != NULL ) {
206 strcat( pn_copy->path, "/" ) ;
207 }
208 //LEVEL_DEBUG( "Alias path so far: %s",pn_copy->path ) ;
209 }
210
211 if ( dirfunc != NULL ) {
212 DIRLOCK;
213 dirfunc(v, pn_copy);
214 DIRUNLOCK;
215 }
216 } else {
217 // Don't want alias substituted
218 if ( dirfunc != NULL ) {
219 DIRLOCK;
220 dirfunc(v, pn);
221 DIRUNLOCK;
222 }
223 }
224 }
225