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