dos.library: Reverted 49008, mixing buffered and unbuffered reads causes wrong data...
[AROS.git] / rom / dos / addpart.c
blob3c61c18bb34cfa70aa32704c46b3a9660a8beecd
1 /*
2 Copyright © 1995-2012, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Combine paths.
6 Lang: English
7 */
8 #include "dos_intern.h"
10 #include <string.h>
12 /*****************************************************************************
14 NAME */
15 #include <proto/dos.h>
17 AROS_LH3(BOOL, AddPart,
19 /* SYNOPSIS */
20 AROS_LHA(STRPTR, dirname, D1),
21 AROS_LHA(CONST_STRPTR, filename, D2),
22 AROS_LHA(ULONG, size, D3),
24 /* LOCATION */
25 struct DosLibrary *, DOSBase, 147, Dos)
27 /* FUNCTION
28 AddPart() will add a file, directory or other path name to a
29 directory path. It will take into account any pre-existing
30 separator characters (':','/').
32 If filename is an absolute path it will replace
33 the current value of dirname.
35 INPUTS
36 dirname - The path to add the new path to.
37 filename - The path you wish added.
38 size - The size of the dirname buffer (must NOT be 0).
40 RESULT
41 Non-zero if everything succeeded, FALSE if the buffer would have
42 overflowed.
44 If the buffer would have overflowed, then dirname will not have
45 been changed.
47 NOTES
49 EXAMPLE
50 UBYTE buffer[80];
51 buffer[0]='\0';
52 AddPart(buffer, "Work:", 80);
53 AddPart(buffer, "Programming/Include/exec", 80);
55 FPuts(Output(), buffer);
56 --> Work:Programming/Include/exec
58 AddPart(buffer, "/graphics", 80);
60 FPuts(Output(), buffer);
61 --> Work:Programming/Include/graphics
63 AddPart(buffer, "gfxmacros.h", 80);
64 FPuts(Output(), buffer);
65 --> Work:Programming/Include/graphics/gfxmacros.h
67 BUGS
69 SEE ALSO
70 FilePart(), PathPart()
72 INTERNALS
74 *****************************************************************************/
76 AROS_LIBFUNC_INIT
78 #if 1
79 /* stegerg: a bit simple, but since the other code does not
80 work correctly. And then even AmigaOS AddPart()
81 does not seem to do things like eliminating
82 "dead" path components like:
84 "test/test2//test3" --> "test/test3"
86 It just makes sure that the path is correct
89 char *stringpos;
90 LONG stringlen;
91 WORD mustaddslash = 0;
93 stringpos = strchr(filename, ':');
94 if (stringpos)
96 if (stringpos == (char *)filename)
98 /* The first char of filename is a ':' */
100 /* Find dirname position to where we copy filename later */
102 stringpos = strchr(dirname, ':');
103 if (!stringpos) stringpos = dirname;
105 else
107 /* Filename is a fully qualified path including
108 volume/device name -> replace dirname with filename */
110 stringpos = dirname;
113 else
115 /* filename did not contain ':' */
117 stringlen = strlen(dirname);
118 stringpos = dirname + stringlen;
120 /* Check if we must add a slash */
122 if (stringlen > 0)
124 if ((stringpos[-1] != ':') && (stringpos[-1] != '/'))
125 mustaddslash = 1;
129 /* Check if dirname buffer is big enough */
131 stringlen = ((LONG)(stringpos - (char *)dirname)) + strlen(filename) + 1 + mustaddslash;
132 if (stringlen <= size)
134 if (mustaddslash) *stringpos++ = '/';
135 strcpy(stringpos, filename);
136 return DOSTRUE;
138 else
140 SetIoErr(ERROR_LINE_TOO_LONG);
141 return DOSFALSE;
144 #else
146 /* stegerg: this is buggy, because in some places it accesses
147 chars in dirname behind the (initial) string in
148 there (after the 0 char). For example:
150 char buffer[256];
152 strcpy(buffer, "LOCALE:Catalogs");
153 AddPart(buffer, "deutsch", 256);
155 gives correct "LOCALE:Catalogs/deutsch"
157 but: exactly the same, but buffer before was used for
158 something else:
160 char buffer[256];
162 strcpy(buffer, "PROGDIR:Catalogs");
163 AddPart(buffer, "deutsch", 256);
165 gives correct "PROGDIR:Catalogs/deutsch"
167 strcpy(buffer, "LOCALE:Catalogs");
168 AddPart(buffer, "deutsch", 256);
170 gives wrong "LOCALE:Catalogs//deutsch"
175 LONG didx, fidx;
176 BOOL gotfull = FALSE;
179 Make sure the buffer wouldn't overflow, also finds the ends
180 of the strings...
183 didx = fidx = 0;
185 while(dirname[didx]) didx++;
186 while(filename[fidx])
189 If this has a colon, and its not the first char,
190 then this is probably a FQ path.
192 if((filename[fidx] == ':') && (fidx != 0))
193 gotfull = TRUE;
195 fidx++;
198 /* If we got a fully qualified path, then just do a copy. */
199 if(gotfull == TRUE)
201 /* +1 for NULL byte */
202 if( fidx + 1 > size ) {
203 SetIoErr(ERROR_LINE_TOO_LONG);
204 return DOSFALSE;
206 while(*filename)
208 *dirname++ = *filename++;
210 *dirname = '\0';
211 return DOSTRUE;
214 /* Otherwise correctly add the subpath on to the end */
215 else
217 /* +1 for NULL byte, +1 for '/' */
218 if((didx + fidx + 2) > size) {
219 SetIoErr(ERROR_LINE_TOO_LONG);
220 return DOSFALSE;
224 Add a '/' onto the end of the current path, unless of course
225 the new path has a ':' or '/' on it already or current path
226 is emtpy (stegerg) ...
228 if( (*filename != '/')
229 && (didx != 0 )
230 && (dirname[didx - 1] != ':')
231 && (dirname[didx - 1] != '/')
234 dirname[didx++] = '/';
238 Handle leading '/'s
240 while (*filename == '/')
242 filename ++;
243 while ((dirname[didx] != '/') && (dirname[didx] != ':') && didx)
244 didx --;
247 if we are at start of dirname buf then break even
248 if there are more leading '/'s
250 if (!didx)
251 break;
254 Another leading '/' ?.
255 Only move up a dir if we are not at the root
257 if ((*filename== '/') && (dirname[didx] != ':'))
258 didx --;
261 /* If at root, don't overwrite the ':' */
262 if (dirname[didx] == ':')
263 didx ++;
265 if filename not only was a number of '/'s but also contained
266 a subpath, then be sure to skip the found '/' of dirname.
268 else if ((dirname[didx] == '/') && *filename)
269 didx ++;
271 /* Now add the parts, making sure to do any backtracking... */
272 while(*filename)
274 if(*filename == ':')
277 Search back for a ':' or the start of the buffer
278 do the ':' test first, so we test for didx = 0 after...
280 while( (dirname[didx] != ':') && didx)
282 didx--;
284 dirname[didx++] = *filename++;
286 else
287 dirname[didx++] = *filename++;
288 } /* while(*filename) */
290 dirname[didx] = '\0';
292 return DOSTRUE;
293 #endif
295 AROS_LIBFUNC_EXIT
296 } /* AddPart */