Add ProgramData to the env var whitelist for running scripts
[cygwin-setup.git] / mkdir.cc
blob20a9ba6b8dc3ac3a8c3854166020a7809a4e05e2
1 /*
2 * Copyright (c) 2000, Red Hat, Inc.
4 * This program is free software; you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation; either version 2 of the License, or
7 * (at your option) any later version.
9 * A copy of the GNU General Public License can be found at
10 * http://www.gnu.org/
12 * Written by DJ Delorie <dj@cygnus.com>
16 /* see mkdir.h */
18 #include "win32.h"
19 #include "ntdll.h"
21 #include <sys/stat.h>
23 #include "mkdir.h"
24 #include "filemanip.h"
25 #include "LogSingleton.h"
27 /* Return 0 on success.
28 A mode of 0 means no POSIX perms. */
29 int
30 mkdir_p (int isadir, const char *in_path, mode_t mode)
32 char saved_char, *slash = 0;
33 char *c;
34 const size_t len = strlen (in_path) + 1;
35 char path[len];
36 DWORD d, gse;
37 WCHAR wpath[len + 6];
39 strcpy (path, in_path);
40 mklongpath (wpath, path, len + 6);
42 d = GetFileAttributesW (wpath);
43 if (d != INVALID_FILE_ATTRIBUTES && d & FILE_ATTRIBUTE_DIRECTORY)
44 return 0;
46 if (isadir)
48 NTSTATUS status;
49 HANDLE dir;
50 UNICODE_STRING upath;
51 OBJECT_ATTRIBUTES attr;
52 IO_STATUS_BLOCK io;
53 SECURITY_DESCRIPTOR sd;
54 acl_t acl;
56 wpath[1] = '?';
57 upath.Length = wcslen (wpath) * sizeof (WCHAR);
58 upath.MaximumLength = upath.Length + sizeof (WCHAR);
59 upath.Buffer = wpath;
60 InitializeObjectAttributes (&attr, &upath, OBJ_CASE_INSENSITIVE, NULL,
61 mode == 0 ? NULL
62 : nt_sec.GetPosixPerms (path, NULL, NULL,
63 S_IFDIR | mode,
64 sd, acl));
65 status = NtCreateFile (&dir, SYNCHRONIZE | READ_CONTROL
66 | FILE_LIST_DIRECTORY,
67 &attr, &io, NULL, FILE_ATTRIBUTE_DIRECTORY,
68 FILE_SHARE_VALID_FLAGS, FILE_CREATE,
69 FILE_DIRECTORY_FILE
70 | FILE_SYNCHRONOUS_IO_NONALERT
71 | FILE_OPEN_FOR_BACKUP_INTENT, NULL, 0);
72 if (NT_SUCCESS (status))
74 NtClose (dir);
75 return 0;
77 else
78 SetLastError (RtlNtStatusToDosError (status));
79 gse = GetLastError ();
80 if (gse != ERROR_PATH_NOT_FOUND && gse != ERROR_FILE_NOT_FOUND)
82 if (gse == ERROR_ALREADY_EXISTS)
84 Log (LOG_TIMESTAMP) << "warning: deleting \"" << path
85 << "\" so I can make a directory there" << endLog;
86 if (DeleteFileW (wpath))
87 return mkdir_p (isadir, path, mode ? 0755 : 0);
89 return 1;
93 for (c = path; *c; c++)
95 if (*c == '/' || *c == '\\')
96 slash = c;
99 if (!slash)
100 return 0;
102 // Trying to create a drive... It's time to give up.
103 if (((slash - path) == 2) && (path[1] == ':'))
104 return 1;
106 saved_char = *slash;
107 *slash = 0;
108 if (mkdir_p (1, path, mode ? 0755 : 0))
110 *slash = saved_char;
111 return 1;
114 *slash = saved_char;
116 if (!isadir)
117 return 0;
119 return mkdir_p (isadir, path, mode);