char *win32_getcwd(char *buf, int maxlen) { int n=0; if(p_GetCurrentDirectoryW) { char *pwszBuf=sm_get_pool_memory(PM_FNAME); pwszBuf=sm_check_pool_memory_size(pwszBuf, maxlen*sizeof(wchar_t)); if((n=p_GetCurrentDirectoryW(maxlen, (LPWSTR)pwszBuf))) n=wchar_2_UTF8(buf, (wchar_t *)pwszBuf, maxlen)-1; sm_free_pool_memory(pwszBuf); } else if(p_GetCurrentDirectoryA) n=p_GetCurrentDirectoryA(maxlen, buf); if(!n || n>maxlen) return NULL; if(n+1 > maxlen) return NULL; if(n!=3) { buf[n]='\\'; buf[n+1]=0; } return buf; }
/* * Generate a valid connect string and the backup command we should execute * in the seperate database controling thread. */ static inline void perform_ado_backup(bpContext *ctx) { plugin_ctx *p_ctx = (plugin_ctx *)ctx->pContext; POOL_MEM ado_connect_string(PM_NAME), ado_query(PM_NAME); POOLMEM *vdsname; /* * If no explicit instance name given usedthe DEFAULT_INSTANCE name. */ if (!p_ctx->instance) { p_ctx->instance = bstrdup(DEFAULT_INSTANCE); } set_ado_connect_string(ctx); vdsname = get_pool_memory(PM_NAME); wchar_2_UTF8(&vdsname, p_ctx->vdsname); switch (p_ctx->backup_level) { case L_INCREMENTAL: Mmsg(ado_query, "BACKUP LOG %s TO VIRTUAL_DEVICE='%s' WITH BLOCKSIZE=%d, BUFFERCOUNT=%d, MAXTRANSFERSIZE=%d", p_ctx->database, vdsname, DEFAULT_BLOCKSIZE, DEFAULT_BUFFERS, DEFAULT_BLOCKSIZE); break; case L_DIFFERENTIAL: Mmsg(ado_query, "BACKUP DATABASE %s TO VIRTUAL_DEVICE='%s' WITH DIFFERENTIAL, BLOCKSIZE=%d, BUFFERCOUNT=%d, MAXTRANSFERSIZE=%d", p_ctx->database, vdsname, DEFAULT_BLOCKSIZE, DEFAULT_BUFFERS, DEFAULT_BLOCKSIZE); break; default: Mmsg(ado_query, "BACKUP DATABASE %s TO VIRTUAL_DEVICE='%s' WITH BLOCKSIZE=%d, BUFFERCOUNT=%d, MAXTRANSFERSIZE=%d", p_ctx->database, vdsname, DEFAULT_BLOCKSIZE, DEFAULT_BUFFERS, DEFAULT_BLOCKSIZE); break; } Dmsg(ctx, dbglvl, "perform_ado_backup: ADO Query '%s'\n", ado_query.c_str()); p_ctx->ado_query = bstrdup(ado_query.c_str()); free_pool_memory(vdsname); }
int readdir_r(DIR *dirp, struct dirent *entry, struct dirent **result) { _dir *dp=(_dir *)dirp; if(dp->valid_w || dp->valid_a) { entry->d_off=dp->offset; // Copy unicode. if(dp->valid_w) { char szBuf[MAX_PATH_UTF8+1]; wchar_2_UTF8(szBuf, dp->data_w.cFileName); dp->offset+=copyin(*entry, szBuf); } else if(dp->valid_a) // copy ansi (only 1 will be valid) dp->offset+=copyin(*entry, dp->data_a.cFileName); *result=entry; // Return entry address. } else { errno=b_errno_win32; return -1; } // Get next file, try unicode first. if(p_FindNextFileW) dp->valid_w=p_FindNextFileW(dp->dirh, &dp->data_w); else if(p_FindNextFileA) dp->valid_a=p_FindNextFileA(dp->dirh, &dp->data_a); else { dp->valid_a=FALSE; dp->valid_w=FALSE; } return 0; }
static int statDir(const char *file, struct stat *sb, uint64_t *winattr) { WIN32_FIND_DATAW info_w; // window's file info WIN32_FIND_DATAA info_a; // window's file info // cache some common vars to make code more transparent DWORD *pdwFileAttributes; DWORD *pnFileSizeHigh; DWORD *pnFileSizeLow; DWORD *pdwReserved0; FILETIME *pftLastAccessTime; FILETIME *pftLastWriteTime; FILETIME *pftCreationTime; /* Oh, cool, another exception: Microsoft doesn't let us do FindFile operations on a Drive, so simply fake root attibutes. */ if(file[1]==':' && !file[2]) { time_t now=time(NULL); sb->st_mode=S_IFDIR; sb->st_mode|=S_IREAD|S_IEXEC|S_IWRITE; sb->st_ctime=now; sb->st_mtime=now; sb->st_atime=now; sb->st_rdev=0; return 0; } HANDLE h=INVALID_HANDLE_VALUE; // use unicode if(p_FindFirstFileW) { char *pwszBuf=sm_get_pool_memory(PM_FNAME); make_win32_path_UTF8_2_wchar(&pwszBuf, file); h=p_FindFirstFileW((LPCWSTR)pwszBuf, &info_w); sm_free_pool_memory(pwszBuf); pdwFileAttributes=&info_w.dwFileAttributes; pdwReserved0 =&info_w.dwReserved0; pnFileSizeHigh =&info_w.nFileSizeHigh; pnFileSizeLow =&info_w.nFileSizeLow; pftLastAccessTime=&info_w.ftLastAccessTime; pftLastWriteTime =&info_w.ftLastWriteTime; pftCreationTime =&info_w.ftCreationTime; // use ASCII } else if (p_FindFirstFileA) { h=p_FindFirstFileA(file, &info_a); pdwFileAttributes=&info_a.dwFileAttributes; pdwReserved0 =&info_a.dwReserved0; pnFileSizeHigh =&info_a.nFileSizeHigh; pnFileSizeLow =&info_a.nFileSizeLow; pftLastAccessTime=&info_a.ftLastAccessTime; pftLastWriteTime =&info_a.ftLastWriteTime; pftCreationTime =&info_a.ftCreationTime; } if(h==INVALID_HANDLE_VALUE) { const char *err = errorString(); /* Note, in creating leading paths, it is normal that the file does not exist. */ LocalFree((void *)err); errno=b_errno_win32; return -1; } else FindClose(h); *winattr=(int64_t)*pdwFileAttributes; /* Graham says: all the following stuff seems rather complicated. It is probably not all needed anymore, since I have added *winattr above, which bacula did not do. One reason for keeping it is that some of the values get converted to unix-style permissions that show up in the long list functionality. I think I would prefer to remove it all at some point. */ sb->st_mode = 0777; // start with everything if(*pdwFileAttributes & FILE_ATTRIBUTE_READONLY) sb->st_mode &= ~(S_IRUSR|S_IRGRP|S_IROTH); if(*pdwFileAttributes & FILE_ATTRIBUTE_SYSTEM) sb->st_mode &= ~S_IRWXO; // remove everything for other if(*pdwFileAttributes & FILE_ATTRIBUTE_HIDDEN) sb->st_mode |= S_ISVTX; // use sticky bit -> hidden sb->st_mode |= S_IFDIR; /* Store reparse/mount point info in st_rdev. Note a Win32 reparse point (junction point) is like a link though it can have many properties (directory link, soft link, hard link, HSM, ... A mount point is a reparse point where another volume is mounted, so it is like a Unix mount point (change of filesystem). */ if(*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) sb->st_rdev=WIN32_MOUNT_POINT; else sb->st_rdev=0; if((*pdwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && (*pdwReserved0 & IO_REPARSE_TAG_MOUNT_POINT)) { sb->st_rdev=WIN32_MOUNT_POINT; /* Now to find out if the directory is a mount point or a reparse point, we must do a song and a dance. Explicitly open the file to read the reparse point, then call DeviceIoControl to find out if it points to a Volume or to a directory. */ h=INVALID_HANDLE_VALUE; if(p_GetFileAttributesW) { char *pwszBuf=sm_get_pool_memory(PM_FNAME); make_win32_path_UTF8_2_wchar(&pwszBuf, file); if(p_CreateFileW) { h=CreateFileW((LPCWSTR)pwszBuf, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); } sm_free_pool_memory(pwszBuf); } else if(p_GetFileAttributesA) { h=CreateFileA(file, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT, NULL); } if(h!=INVALID_HANDLE_VALUE) { char dummy[1000]; REPARSE_DATA_BUFFER *rdb=(REPARSE_DATA_BUFFER *)dummy; rdb->ReparseTag=IO_REPARSE_TAG_MOUNT_POINT; DWORD bytes; bool ok; ok=DeviceIoControl(h, FSCTL_GET_REPARSE_POINT, NULL, 0, // in buffer, bytes (LPVOID)rdb, (DWORD)sizeof(dummy), // out buffer, btyes (LPDWORD)&bytes, (LPOVERLAPPED)0); if(ok) { char *utf8=sm_get_pool_memory(PM_NAME); wchar_2_UTF8(utf8, (wchar_t *) rdb->SymbolicLinkReparseBuffer.PathBuffer); if(!strncasecmp(utf8, "\\??\\volume{", 11)) sb->st_rdev=WIN32_MOUNT_POINT; else // Points to a directory so we ignore it. sb->st_rdev=WIN32_JUNCTION_POINT; sm_free_pool_memory(utf8); } CloseHandle(h); } } sb->st_size=*pnFileSizeHigh; sb->st_size<<=32; sb->st_size|=*pnFileSizeLow; sb->st_blksize=4096; sb->st_blocks=(uint32_t)(sb->st_size+4095)/4096; sb->st_atime=cvt_ftime_to_utime(*pftLastAccessTime); sb->st_mtime=cvt_ftime_to_utime(*pftLastWriteTime); sb->st_ctime=cvt_ftime_to_utime(*pftCreationTime); return 0; }
char* win32_cgets (char* buffer, int len) { /* We use console ReadConsoleA / ReadConsoleW to be able to read unicode from the win32 console and fallback if seomething fails. */ HANDLE hIn=GetStdHandle (STD_INPUT_HANDLE); if(hIn && (hIn!=INVALID_HANDLE_VALUE) && p_WideCharToMultiByte && p_MultiByteToWideChar) { DWORD dwRead; wchar_t wszBuf[1024]; char szBuf[1024]; // NT and unicode conversion. if(ReadConsoleW(hIn, wszBuf, 1024, &dwRead, NULL)) { // Null terminate at end. if(wszBuf[dwRead-1]==L'\n') { wszBuf[dwRead-1]=L'\0'; dwRead--; } if(wszBuf[dwRead-1]==L'\r') { wszBuf[dwRead-1]=L'\0'; dwRead--; } wchar_2_UTF8(buffer, wszBuf, len); return buffer; } // Win 9x and unicode conversion. if(ReadConsoleA(hIn, szBuf, 1024, &dwRead, NULL)) { // Null terminate at end. if(szBuf[dwRead-1]==L'\n') { szBuf[dwRead-1]=L'\0'; dwRead--; } if(szBuf[dwRead-1]==L'\r') { szBuf[dwRead-1]=L'\0'; dwRead--; } // Convert from ansii to wchar_t. p_MultiByteToWideChar(GetConsoleCP(), 0, szBuf, -1, wszBuf, 1024); // Convert from wchar_t to UTF-8. if(wchar_2_UTF8(buffer, wszBuf, len)) return buffer; } } // Fallback. if(fgets(buffer, len, stdin)) return buffer; return NULL; }
/* * Generate a valid connect string and the restore command we should execute * in the seperate database controling thread. */ static inline void perform_ado_restore(bpContext *ctx) { POOL_MEM ado_query(PM_NAME), temp(PM_NAME); POOLMEM *vdsname; plugin_ctx *p_ctx = (plugin_ctx *)ctx->pContext; /* * If no explicit instance name given use the DEFAULT_INSTANCE name. */ if (!p_ctx->instance) { p_ctx->instance = bstrdup(DEFAULT_INSTANCE); } set_ado_connect_string(ctx); vdsname = get_pool_memory(PM_NAME); wchar_2_UTF8(&vdsname, p_ctx->vdsname); switch (p_ctx->backup_level) { case L_INCREMENTAL: Mmsg(ado_query, "RESTORE LOG %s FROM VIRTUAL_DEVICE='%s' WITH BLOCKSIZE=%d, BUFFERCOUNT=%d, MAXTRANSFERSIZE=%d, %s", p_ctx->database, vdsname, DEFAULT_BLOCKSIZE, DEFAULT_BUFFERS, DEFAULT_BLOCKSIZE, p_ctx->DoNoRecovery ? "NORECOVERY" : "RECOVERY"); break; default: Mmsg(ado_query, "RESTORE DATABASE %s FROM VIRTUAL_DEVICE='%s' WITH BLOCKSIZE=%d, BUFFERCOUNT=%d, MAXTRANSFERSIZE=%d, %s", p_ctx->database, vdsname, DEFAULT_BLOCKSIZE, DEFAULT_BUFFERS, DEFAULT_BLOCKSIZE, p_ctx->DoNoRecovery ? "NORECOVERY" : "RECOVERY"); break; } /* * See if we need to insert any stopbeforemark arguments. */ if (p_ctx->stopbeforemark) { Mmsg(temp, ", STOPBEFOREMARK = '%s'", p_ctx->stopbeforemark); pm_strcat(ado_query, temp.c_str()); } /* * See if we need to insert any stopatmark arguments. */ if (p_ctx->stopatmark) { Mmsg(temp, ", STOPATMARK = '%s'", p_ctx->stopatmark); pm_strcat(ado_query, temp.c_str()); } /* * See if we need to insert any stopat arguments. */ if (p_ctx->stopat) { Mmsg(temp, ", STOPAT = '%s'", p_ctx->stopat); pm_strcat(ado_query, temp.c_str()); } /* * See if we need to insert the REPLACE option. */ if (p_ctx->ForceReplace) { pm_strcat(ado_query, ", REPLACE"); } Dmsg(ctx, dbglvl, "perform_ado_restore: ADO Query '%s'\n", ado_query.c_str()); p_ctx->ado_query = bstrdup(ado_query.c_str()); free_pool_memory(vdsname); }