1 /*-------------------------------------------------------------------------
4 * directory handling functions
6 * Portions Copyright (c) 1996-2010, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
9 * This includes replacement versions of functions that work on
10 * Win32 (NT4 and newer).
13 * $PostgreSQL: pgsql/src/port/dirmod.c,v 1.60 2010/01/02 16:58:13 momjian Exp $
15 *-------------------------------------------------------------------------
21 #include "postgres_fe.h"
24 /* Don't modify declarations in system headers */
25 #if defined(WIN32) || defined(__CYGWIN__)
34 #if defined(WIN32) || defined(__CYGWIN__)
39 #include <w32api/winioctl.h>
47 * On Windows, call non-macro versions of palloc; we can't reference
48 * CurrentMemoryContext in this file because of PGDLLIMPORT conflict.
50 #if defined(WIN32) || defined(__CYGWIN__)
53 #define palloc(sz) pgport_palloc(sz)
54 #define pstrdup(str) pgport_pstrdup(str)
59 * In frontend, fake palloc behavior with these
63 #define palloc(sz) fe_palloc(sz)
64 #define pstrdup(str) fe_pstrdup(str)
65 #define repalloc(pointer,sz) fe_repalloc(pointer,sz)
66 #define pfree(pointer) free(pointer)
73 if ((res = malloc(size)) == NULL)
75 fprintf(stderr, _("out of memory\n"));
82 fe_pstrdup(const char *string)
86 if ((res = strdup(string)) == NULL)
88 fprintf(stderr, _("out of memory\n"));
95 fe_repalloc(void *pointer, Size size)
99 if ((res = realloc(pointer, size)) == NULL)
101 fprintf(stderr, _("out of memory\n"));
106 #endif /* FRONTEND */
109 #if defined(WIN32) || defined(__CYGWIN__)
115 pgrename(const char *from, const char *to)
120 * We need to loop because even though PostgreSQL uses flags that allow
121 * rename while the file is open, other applications might have the file
122 * open without those flags. However, we won't wait indefinitely for
123 * someone else to close the file, as the caller might be holding locks
124 * and blocking other backends.
126 #if defined(WIN32) && !defined(__CYGWIN__)
127 while (!MoveFileEx(from, to, MOVEFILE_REPLACE_EXISTING))
129 while (rename(from, to) < 0)
132 #if defined(WIN32) && !defined(__CYGWIN__)
133 DWORD err = GetLastError();
138 * Modern NT-based Windows versions return ERROR_SHARING_VIOLATION
139 * if another process has the file open without FILE_SHARE_DELETE.
140 * ERROR_LOCK_VIOLATION has also been seen with some anti-virus
141 * software. This used to check for just ERROR_ACCESS_DENIED, so
142 * presumably you can get that too with some OS versions. We don't
143 * expect real permission errors where we currently use rename().
145 if (err != ERROR_ACCESS_DENIED &&
146 err != ERROR_SHARING_VIOLATION &&
147 err != ERROR_LOCK_VIOLATION)
154 if (++loops > 100) /* time out after 10 sec */
156 pg_usleep(100000); /* us */
166 pgunlink(const char *path)
171 * We need to loop because even though PostgreSQL uses flags that allow
172 * unlink while the file is open, other applications might have the file
173 * open without those flags. However, we won't wait indefinitely for
174 * someone else to close the file, as the caller might be holding locks
175 * and blocking other backends.
181 if (++loops > 100) /* time out after 10 sec */
183 pg_usleep(100000); /* us */
188 /* We undefined these above; now redefine for possible use below */
189 #define rename(from, to) pgrename(from, to)
190 #define unlink(path) pgunlink(path)
191 #endif /* defined(WIN32) || defined(__CYGWIN__) */
194 #if defined(WIN32) && !defined(__CYGWIN__) /* Cygwin has its own symlinks */
199 * This struct is a replacement for REPARSE_DATA_BUFFER which is defined in VC6 winnt.h
200 * but omitted in later SDK functions.
201 * We only need the SymbolicLinkReparseBuffer part of the original struct's union.
206 WORD ReparseDataLength;
208 /* SymbolicLinkReparseBuffer */
209 WORD SubstituteNameOffset;
210 WORD SubstituteNameLength;
211 WORD PrintNameOffset;
212 WORD PrintNameLength;
214 } REPARSE_JUNCTION_DATA_BUFFER;
216 #define REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE \
217 FIELD_OFFSET(REPARSE_JUNCTION_DATA_BUFFER, SubstituteNameOffset)
221 * pgsymlink - uses Win32 junction points
223 * For reference: http://www.codeproject.com/w2k/junctionpoints.asp
226 pgsymlink(const char *oldpath, const char *newpath)
230 char buffer[MAX_PATH * sizeof(WCHAR) + sizeof(REPARSE_JUNCTION_DATA_BUFFER)];
231 char nativeTarget[MAX_PATH];
232 char *p = nativeTarget;
233 REPARSE_JUNCTION_DATA_BUFFER *reparseBuf = (REPARSE_JUNCTION_DATA_BUFFER *) buffer;
235 CreateDirectory(newpath, 0);
236 dirhandle = CreateFile(newpath, GENERIC_READ | GENERIC_WRITE,
238 FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0);
240 if (dirhandle == INVALID_HANDLE_VALUE)
243 /* make sure we have an unparsed native win32 path */
244 if (memcmp("\\??\\", oldpath, 4))
245 sprintf(nativeTarget, "\\??\\%s", oldpath);
247 strcpy(nativeTarget, oldpath);
249 while ((p = strchr(p, '/')) != 0)
252 len = strlen(nativeTarget) * sizeof(WCHAR);
253 reparseBuf->ReparseTag = IO_REPARSE_TAG_MOUNT_POINT;
254 reparseBuf->ReparseDataLength = len + 12;
255 reparseBuf->Reserved = 0;
256 reparseBuf->SubstituteNameOffset = 0;
257 reparseBuf->SubstituteNameLength = len;
258 reparseBuf->PrintNameOffset = len + sizeof(WCHAR);
259 reparseBuf->PrintNameLength = 0;
260 MultiByteToWideChar(CP_ACP, 0, nativeTarget, -1,
261 reparseBuf->PathBuffer, MAX_PATH);
264 * FSCTL_SET_REPARSE_POINT is coded differently depending on SDK version;
265 * we use our own definition
267 if (!DeviceIoControl(dirhandle,
268 CTL_CODE(FILE_DEVICE_FILE_SYSTEM, 41, METHOD_BUFFERED, FILE_ANY_ACCESS),
270 reparseBuf->ReparseDataLength + REPARSE_JUNCTION_DATA_BUFFER_HEADER_SIZE,
276 FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
277 NULL, GetLastError(),
278 MAKELANGID(LANG_ENGLISH, SUBLANG_DEFAULT),
279 (LPSTR) &msg, 0, NULL);
282 (errcode_for_file_access(),
283 errmsg("could not set junction for \"%s\": %s",
284 nativeTarget, msg)));
286 fprintf(stderr, _("could not set junction for \"%s\": %s\n"),
291 CloseHandle(dirhandle);
292 RemoveDirectory(newpath);
296 CloseHandle(dirhandle);
300 #endif /* defined(WIN32) && !defined(__CYGWIN__) */
306 * return a list of the names of objects in the argument directory. Caller
307 * must call pgfnames_cleanup later to free the memory allocated by this
311 pgfnames(const char *path)
317 int fnsize = 200; /* enough for many small dbs */
323 elog(WARNING, "could not open directory \"%s\": %m", path);
325 fprintf(stderr, _("could not open directory \"%s\": %s\n"),
326 path, strerror(errno));
331 filenames = (char **) palloc(fnsize * sizeof(char *));
334 while ((file = readdir(dir)) != NULL)
336 if (strcmp(file->d_name, ".") != 0 && strcmp(file->d_name, "..") != 0)
338 if (numnames + 1 >= fnsize)
341 filenames = (char **) repalloc(filenames,
342 fnsize * sizeof(char *));
344 filenames[numnames++] = pstrdup(file->d_name);
351 * This fix is in mingw cvs (runtime/mingwex/dirent.c rev 1.4), but not in
354 if (GetLastError() == ERROR_NO_MORE_FILES)
360 elog(WARNING, "could not read directory \"%s\": %m", path);
362 fprintf(stderr, _("could not read directory \"%s\": %s\n"),
363 path, strerror(errno));
367 filenames[numnames] = NULL;
378 * deallocate memory used for filenames
381 pgfnames_cleanup(char **filenames)
385 for (fn = filenames; *fn; fn++)
395 * Delete a directory tree recursively.
396 * Assumes path points to a valid directory.
397 * Deletes everything under path.
398 * If rmtopdir is true deletes the directory too.
399 * Returns true if successful, false if there was any problem.
400 * (The details of the problem are reported already, so caller
401 * doesn't really have to say anything more, but most do.)
404 rmtree(const char *path, bool rmtopdir)
407 char pathbuf[MAXPGPATH];
413 * we copy all the names out of the directory before we start modifying
416 filenames = pgfnames(path);
418 if (filenames == NULL)
421 /* now we have the names we can start removing things */
422 for (filename = filenames; *filename; filename++)
424 snprintf(pathbuf, MAXPGPATH, "%s/%s", path, *filename);
427 * It's ok if the file is not there anymore; we were just about to
430 * This is not an academic possibility. One scenario where this
431 * happens is when bgwriter has a pending unlink request for a file in
432 * a database that's being dropped. In dropdb(), we call
433 * ForgetDatabaseFsyncRequests() to flush out any such pending unlink
434 * requests, but because that's asynchronous, it's not guaranteed that
435 * the bgwriter receives the message in time.
437 if (lstat(pathbuf, &statbuf) != 0)
442 elog(WARNING, "could not stat file or directory \"%s\": %m",
445 fprintf(stderr, _("could not stat file or directory \"%s\": %s\n"),
446 pathbuf, strerror(errno));
453 if (S_ISDIR(statbuf.st_mode))
455 /* call ourselves recursively for a directory */
456 if (!rmtree(pathbuf, true))
458 /* we already reported the error */
464 if (unlink(pathbuf) != 0)
469 elog(WARNING, "could not remove file or directory \"%s\": %m",
472 fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"),
473 pathbuf, strerror(errno));
483 if (rmdir(path) != 0)
486 elog(WARNING, "could not remove file or directory \"%s\": %m",
489 fprintf(stderr, _("could not remove file or directory \"%s\": %s\n"),
490 path, strerror(errno));
496 pgfnames_cleanup(filenames);
502 #if defined(WIN32) && !defined(__CYGWIN__)
507 * The stat() function in win32 is not guaranteed to update the st_size
508 * field when run. So we define our own version that uses the Win32 API
509 * to update this field.
512 pgwin32_safestat(const char *path, struct stat * buf)
515 WIN32_FILE_ATTRIBUTE_DATA attr;
521 if (!GetFileAttributesEx(path, GetFileExInfoStandard, &attr))
523 _dosmaperr(GetLastError());
528 * XXX no support for large files here, but we don't do that in general on
531 buf->st_size = attr.nFileSizeLow;