Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(37)

Side by Side Diff: tools/junction/junction.c

Issue 9693033: Utility to create NTFS junctions points. (Closed) Base URL: http://git.chromium.org/chromium/src.git@master
Patch Set: Added file system check and less funny error message. Created 8 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 //
5 // This is a simple utility for creating NTFS junction points on XP and later
6 // versions of Windows.
7
8 #define _WIN32_WINNT 0x0500
9
10 #include <stdio.h>
11 #include <windows.h>
12
13 // This struct definition is absent from the system header files,
14 // but is described here:
15 // http://msdn.microsoft.com/en-us/library/ff552012.aspx
16 typedef struct _REPARSE_DATA_BUFFER {
17 ULONG ReparseTag;
18 USHORT ReparseDataLength;
19 USHORT Reserved;
20 union {
21 struct {
22 USHORT SubstituteNameOffset;
23 USHORT SubstituteNameLength;
24 USHORT PrintNameOffset;
25 USHORT PrintNameLength;
26 ULONG Flags;
27 WCHAR PathBuffer[1];
28 } SymbolicLinkReparseBuffer;
29 struct {
30 USHORT SubstituteNameOffset;
31 USHORT SubstituteNameLength;
32 USHORT PrintNameOffset;
33 USHORT PrintNameLength;
34 WCHAR PathBuffer[1];
35 } MountPointReparseBuffer;
36 struct {
37 UCHAR DataBuffer[1];
38 } GenericReparseBuffer;
39 };
40 } REPARSE_DATA_BUFFER;
41
42 int main(int argc, char *argv[])
43 {
44 char buf[MAX_PATH*sizeof(WCHAR) + sizeof(REPARSE_DATA_BUFFER)] = {'\0'};
45 char* dest_path = NULL;
M-A Ruel 2012/05/23 00:28:09 I highly recommend converting everything to wchar_
46 char* src_path = NULL;
47 char* src_link = NULL;
48 char* src_vol = NULL;
49 char* dest_vol = NULL;
50 HANDLE dir = NULL;
51 REPARSE_DATA_BUFFER* reparse = (REPARSE_DATA_BUFFER*) buf;
52 int path_len = 0, data_len = 0;
53 DWORD fs_flags = 0;
54 DWORD ioctl_return = 0xdeadbeef;
55
56 // To allow this to be used as a drop-in replacement for the posix ln command,
57 // allow (and ignore) extra flags.
58 if (argc != 3 && (argc !=4 || *argv[1] != '-')) {
59 fputs("Usage: junction <destination dir> <source dir>\n", stderr);
M-A Ruel 2012/05/23 00:28:09 Why fputs here but fprintf around lines 91-92?
60 return -1;
61 }
62
63 src_path = argv[argc-2];
64 path_len = strlen(src_path);
65 if (src_path[path_len-1] == '\\')
66 src_path[path_len-1] = '\0';
67
68 dest_path = argv[argc-1];
69 path_len = strlen(dest_path);
70 if (dest_path[path_len-1] == '\\')
71 dest_path[path_len-1] = '\0';
72
73 if (GetFileAttributes(src_path) == INVALID_FILE_ATTRIBUTES) {
74 fprintf(stderr, "%s: invalid file attributes.\n", src_path);
75 return -1;
76 }
77
78 if (!GetVolumePathName(src_path, buf, MAX_PATH)) {
79 fprintf(stderr, "Couldn't get volume name for '%s'.\n", src_path);
80 return -1;
81 }
82 src_vol = _strdup(buf);
M-A Ruel 2012/05/23 00:28:09 Head explodes. :)
83
84 if (!GetVolumePathName(dest_path, buf, MAX_PATH)) {
85 fprintf(stderr, "Couldn't get volume name for '%s'.\n", dest_path);
86 return -1;
87 }
88 dest_vol = _strdup(buf);
89
90 if (strcmp(src_vol, dest_vol)) {
91 fprintf(stderr, "Cannot create junction point across volume boundary.\n");
92 fprintf(stderr, " (from volume '%s' to volume '%s')\n", src_vol, dest_vol);
93 return -1;
94 }
95
96 GetVolumeInformation(src_vol, NULL, 0, NULL, NULL, &fs_flags, buf, MAX_PATH);
97 if (!(fs_flags & FILE_SUPPORTS_REPARSE_POINTS)) {
98 fprintf(stderr, "File system type '%s' does not support reparse points.\n",
99 buf);
100 return -1;
101 }
102
103 // End of input sanity checks; file system modifications may now occur.
104
105 if (GetFileAttributes(dest_path) == INVALID_FILE_ATTRIBUTES) {
106 if (!CreateDirectory(dest_path, NULL)) {
107 switch(GetLastError()) {
108 case ERROR_ALREADY_EXISTS:
109 fprintf(stderr, "Can't create directory %s because it already exists "
110 "(this should never happen).\n", dest_path);
111 return -1;
112 break;
113 case ERROR_PATH_NOT_FOUND:
114 fprintf(stderr, "Can't create directory %s because some part of the "
115 "intermediate path doesn't exist.", dest_path);
116 return -1;
117 break;
118 default:
119 fprintf(stderr, "Unknown error occurred while trying to create "
nsylvain 2012/03/16 18:24:18 you should probably print the error here.
120 "directory %s.", dest_path);
121 return -1;
122 break;
123 }
124 }
125 }
126
127 dir = CreateFile(dest_path,
128 GENERIC_WRITE,
129 0,
130 NULL,
131 OPEN_EXISTING,
132 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS,
133 NULL);
134
135 strcpy_s(buf, 5, "\\??\\");
136 GetFullPathName(src_path, MAX_PATH, buf+4, NULL);
137 src_link = _strdup(buf);
138
139 memset(buf, 0, sizeof(buf));
140 path_len = MultiByteToWideChar(CP_ACP,
141 0,
142 src_link,
143 -1,
144 reparse->MountPointReparseBuffer.PathBuffer,
145 MAX_PATH*sizeof(WCHAR));
146
147 reparse->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
148 reparse->ReparseDataLength = (path_len+2)*sizeof(WCHAR) + 6;
149 reparse->MountPointReparseBuffer.SubstituteNameLength =
150 (path_len-1) * sizeof(WCHAR);
151 reparse->MountPointReparseBuffer.PrintNameOffset =
152 path_len * sizeof(WCHAR);
153 data_len = reparse->ReparseDataLength + 8;
154
155 if (!DeviceIoControl(dir,
156 FSCTL_SET_REPARSE_POINT,
157 &buf,
158 data_len,
159 NULL,
160 0,
161 &ioctl_return,
162 NULL)) {
163 fprintf(stderr, "Junction point creation failed (ioctl_return=0x%x) (%d)\n",
164 ioctl_return, GetLastError());
165 return 1;
166 }
167
168 return 0;
169 }
OLDNEW
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698