xref: /reactos/sdk/lib/crt/stdlib/makepath_s.c (revision c2c66aff)
1 /*
2  * PROJECT:     ReactOS CRT library
3  * LICENSE:     See COPYING in the top level directory
4  * FILE:        lib/sdk/crt/stdlib/makepath_s.c
5  * PURPOSE:     Creates a path
6  * PROGRAMMERS: Wine team
7  *              Copyright 1996,1998 Marcus Meissner
8  *              Copyright 1996 Jukka Iivonen
9  *              Copyright 1997,2000 Uwe Bonnes
10  *              Copyright 2000 Jon Griffiths
11  *
12  */
13 
14 #include <precomp.h>
15 #include <stdlib.h>
16 #include <string.h>
17 
18 /*********************************************************************
19  *		_makepath_s (MSVCRT.@)
20  *
21  * Safe version of _makepath.
22  */
_makepath_s(char * path,size_t size,const char * drive,const char * directory,const char * filename,const char * extension)23 int CDECL _makepath_s(char *path, size_t size, const char *drive,
24                       const char *directory, const char *filename,
25                       const char *extension)
26 {
27     char *p = path;
28 
29     if (!path || !size)
30     {
31         *_errno() = EINVAL;
32         return EINVAL;
33     }
34 
35     if (drive && drive[0])
36     {
37         if (size <= 2)
38             goto range;
39 
40         *p++ = drive[0];
41         *p++ = ':';
42         size -= 2;
43     }
44 
45     if (directory && directory[0])
46     {
47         size_t len = strlen(directory);
48         unsigned int needs_separator = directory[len - 1] != '/' && directory[len - 1] != '\\';
49         size_t copylen = min(size - 1, len);
50 
51         if (size < 2)
52             goto range;
53 
54         memmove(p, directory, copylen);
55 
56         if (size <= len)
57             goto range;
58 
59         p += copylen;
60         size -= copylen;
61 
62         if (needs_separator)
63         {
64             if (size < 2)
65                 goto range;
66 
67             *p++ = '\\';
68             size -= 1;
69         }
70     }
71 
72     if (filename && filename[0])
73     {
74         size_t len = strlen(filename);
75         size_t copylen = min(size - 1, len);
76 
77         if (size < 2)
78             goto range;
79 
80         memmove(p, filename, copylen);
81 
82         if (size <= len)
83             goto range;
84 
85         p += len;
86         size -= len;
87     }
88 
89     if (extension && extension[0])
90     {
91         size_t len = strlen(extension);
92         unsigned int needs_period = extension[0] != '.';
93         size_t copylen;
94 
95         if (size < 2)
96             goto range;
97 
98         if (needs_period)
99         {
100             *p++ = '.';
101             size -= 1;
102         }
103 
104         copylen = min(size - 1, len);
105         memcpy(p, extension, copylen);
106 
107         if (size <= len)
108             goto range;
109 
110         p += copylen;
111     }
112 
113     *p = '\0';
114     return 0;
115 
116 range:
117     path[0] = '\0';
118     *_errno() = ERANGE;
119     return ERANGE;
120 }
121