]>
Commit | Line | Data |
---|---|---|
23c9e63c DD |
1 | /* |
2 | * Copyright (c) 2000, Red Hat, Inc. | |
3 | * | |
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. | |
8 | * | |
9 | * A copy of the GNU General Public License can be found at | |
10 | * http://www.gnu.org/ | |
11 | * | |
12 | * Written by DJ Delorie <dj@cygnus.com> | |
13 | * | |
14 | */ | |
15 | ||
16 | /* see mkdir.h */ | |
17 | ||
18 | #include "win32.h" | |
6dcfeb7d | 19 | #include "ntdll.h" |
89cc2408 CV |
20 | |
21 | #include <sys/stat.h> | |
23c9e63c DD |
22 | |
23 | #include "mkdir.h" | |
2f0315ad | 24 | #include "filemanip.h" |
781a9555 | 25 | #include "LogSingleton.h" |
23c9e63c | 26 | |
70e4bf04 | 27 | /* Return 0 on success. |
a5104a04 | 28 | A mode of 0 means no POSIX perms. */ |
23c9e63c | 29 | int |
b41c2908 | 30 | mkdir_p (int isadir, const char *in_path, mode_t mode) |
23c9e63c DD |
31 | { |
32 | char saved_char, *slash = 0; | |
33 | char *c; | |
2f0315ad CV |
34 | const size_t len = strlen (in_path) + 1; |
35 | char path[len]; | |
aa1e3b4d | 36 | DWORD d, gse; |
2f0315ad CV |
37 | WCHAR wpath[len + 6]; |
38 | ||
85b43844 | 39 | strcpy (path, in_path); |
1e029da2 | 40 | mklongpath (wpath, path, len + 6); |
23c9e63c | 41 | |
1e029da2 | 42 | d = GetFileAttributesW (wpath); |
2f0315ad | 43 | if (d != INVALID_FILE_ATTRIBUTES && d & FILE_ATTRIBUTE_DIRECTORY) |
23c9e63c DD |
44 | return 0; |
45 | ||
46 | if (isadir) | |
47 | { | |
1e029da2 YS |
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; | |
55 | ||
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)) | |
73 | { | |
74 | NtClose (dir); | |
75 | return 0; | |
76 | } | |
77 | else | |
78 | SetLastError (RtlNtStatusToDosError (status)); | |
23c9e63c | 79 | gse = GetLastError (); |
89725f30 | 80 | if (gse != ERROR_PATH_NOT_FOUND && gse != ERROR_FILE_NOT_FOUND) |
23c9e63c DD |
81 | { |
82 | if (gse == ERROR_ALREADY_EXISTS) | |
83 | { | |
781a9555 JT |
84 | Log (LOG_TIMESTAMP) << "warning: deleting \"" << path |
85 | << "\" so I can make a directory there" << endLog; | |
1e029da2 | 86 | if (DeleteFileW (wpath)) |
d2a5fdfb | 87 | return mkdir_p (isadir, path, mode ? 0755 : 0); |
23c9e63c DD |
88 | } |
89 | return 1; | |
90 | } | |
91 | } | |
92 | ||
85b43844 | 93 | for (c = path; *c; c++) |
23c9e63c | 94 | { |
23c9e63c DD |
95 | if (*c == '/' || *c == '\\') |
96 | slash = c; | |
97 | } | |
98 | ||
99 | if (!slash) | |
100 | return 0; | |
101 | ||
f2e49cf8 RC |
102 | // Trying to create a drive... It's time to give up. |
103 | if (((slash - path) == 2) && (path[1] == ':')) | |
104 | return 1; | |
105 | ||
23c9e63c DD |
106 | saved_char = *slash; |
107 | *slash = 0; | |
d2a5fdfb | 108 | if (mkdir_p (1, path, mode ? 0755 : 0)) |
23c9e63c DD |
109 | { |
110 | *slash = saved_char; | |
111 | return 1; | |
112 | } | |
f2e49cf8 | 113 | |
23c9e63c DD |
114 | *slash = saved_char; |
115 | ||
116 | if (!isadir) | |
117 | return 0; | |
118 | ||
b41c2908 | 119 | return mkdir_p (isadir, path, mode); |
23c9e63c | 120 | } |