static uint32 disk_create_fullpath(IRP * irp, FILE_INFO * finfo, const char * fullpath) { int mode = S_IRWXU | S_IRWXG | S_IROTH | S_IXOTH; int flags = 0; char * p; struct stat file_stat; if (stat(fullpath, &file_stat) == 0) { finfo->is_dir = S_ISDIR(file_stat.st_mode); } else { finfo->is_dir = ((irp->createOptions & FILE_DIRECTORY_FILE) ? 1 : 0); } if (finfo->is_dir) { if (irp->createDisposition == FILE_CREATE) { if (mkdir(fullpath, mode) != 0) return get_error_status(); } finfo->dir = opendir(fullpath); if (finfo->dir == NULL) return get_error_status(); } else { switch (irp->createDisposition) { case FILE_SUPERSEDE: flags = O_TRUNC | O_CREAT; break; case FILE_OPEN: break; case FILE_CREATE: flags |= O_CREAT | O_EXCL; break; case FILE_OPEN_IF: flags |= O_CREAT; break; case FILE_OVERWRITE: flags |= O_TRUNC; break; case FILE_OVERWRITE_IF: flags |= O_TRUNC | O_CREAT; break; default: return RD_STATUS_INVALID_PARAMETER; } if ((irp->desiredAccess & GENERIC_ALL) || (irp->desiredAccess & GENERIC_WRITE) || (irp->desiredAccess & FILE_WRITE_DATA) || (irp->desiredAccess & FILE_APPEND_DATA)) { flags |= O_RDWR; } else { flags |= O_RDONLY; } finfo->file = open(fullpath, flags, mode); if (finfo->file == -1) return get_error_status(); } if (stat(fullpath, &finfo->file_stat) != 0) { return RD_STATUS_NO_SUCH_FILE; } p = strrchr(fullpath, '/'); finfo->file_attr = get_file_attribute((p ? p + 1 : fullpath), &finfo->file_stat); return RD_STATUS_SUCCESS; }
static uint32 disk_query_directory(IRP * irp, uint8 initialQuery, const char * path) { DISK_DEVICE_INFO * info; FILE_INFO * finfo; char * p; uint32 status; char * buf; int size; int len; struct dirent * pdirent; struct stat file_stat; uint32 attr; LLOGLN(10, ("disk_query_directory: class=%d id=%d init=%d path=%s", irp->infoClass, irp->fileID, initialQuery, path)); finfo = disk_get_file_info(irp->dev, irp->fileID); if (finfo == NULL || finfo->dir == NULL) { LLOGLN(0, ("disk_query_directory: invalid file id")); return RD_STATUS_INVALID_HANDLE; } info = (DISK_DEVICE_INFO *) irp->dev->info; if (initialQuery) { if (finfo->pattern) free(finfo->pattern); p = strrchr(path, '\\'); p = (p ? p + 1 : (char *)path); finfo->pattern = malloc(strlen(p) + 1); strcpy(finfo->pattern, p); rewinddir(finfo->dir); } status = RD_STATUS_SUCCESS; buf = NULL; size = 0; pdirent = readdir(finfo->dir); while (pdirent && finfo->pattern[0] && fnmatch(finfo->pattern, pdirent->d_name, 0) != 0) pdirent = readdir(finfo->dir); if (pdirent == NULL) { return RD_STATUS_NO_MORE_FILES; } memset(&file_stat, 0, sizeof(struct stat)); p = malloc(strlen(finfo->fullpath) + strlen(pdirent->d_name) + 2); sprintf(p, "%s/%s", finfo->fullpath, pdirent->d_name); if (stat(p, &file_stat) != 0) { LLOGLN(0, ("disk_query_directory: stat %s failed (%i)\n", p, errno)); } free(p); attr = get_file_attribute(pdirent->d_name, &file_stat); switch (irp->infoClass) { case FileBothDirectoryInformation: size = 93 + strlen(pdirent->d_name) * 2; buf = malloc(size); memset(buf, 0, size); SET_UINT32(buf, 0, 0); /* NextEntryOffset */ SET_UINT32(buf, 4, 0); /* FileIndex */ SET_UINT64(buf, 8, get_rdp_filetime(file_stat.st_ctime < file_stat.st_mtime ? file_stat.st_ctime : file_stat.st_mtime)); /* CreationTime */ SET_UINT64(buf, 16, get_rdp_filetime(file_stat.st_atime)); /* LastAccessTime */ SET_UINT64(buf, 24, get_rdp_filetime(file_stat.st_mtime)); /* LastWriteTime */ SET_UINT64(buf, 32, get_rdp_filetime(file_stat.st_ctime)); /* ChangeTime */ SET_UINT64(buf, 40, file_stat.st_size); /* EndOfFile */ SET_UINT64(buf, 48, file_stat.st_size); /* AllocationSize */ SET_UINT32(buf, 56, attr); /* FileAttributes */ SET_UINT32(buf, 64, 0); /* EaSize */ SET_UINT8(buf, 68, 0); /* ShortNameLength */ /* [MS-FSCC] has one byte padding here but RDP does not! */ //SET_UINT8(buf, 69, 0); /* Reserved */ /* ShortName 24 bytes */ len = freerdp_set_wstr(buf + 93, size - 93, pdirent->d_name, strlen(pdirent->d_name)); SET_UINT32(buf, 60, len); /* FileNameLength */ size = 93 + len; break; case FileFullDirectoryInformation: size = 68 + strlen(pdirent->d_name) * 2; buf = malloc(size); memset(buf, 0, size); SET_UINT32(buf, 0, 0); /* NextEntryOffset */ SET_UINT32(buf, 4, 0); /* FileIndex */ SET_UINT64(buf, 8, get_rdp_filetime(file_stat.st_ctime < file_stat.st_mtime ? file_stat.st_ctime : file_stat.st_mtime)); /* CreationTime */ SET_UINT64(buf, 16, get_rdp_filetime(file_stat.st_atime)); /* LastAccessTime */ SET_UINT64(buf, 24, get_rdp_filetime(file_stat.st_mtime)); /* LastWriteTime */ SET_UINT64(buf, 32, get_rdp_filetime(file_stat.st_ctime)); /* ChangeTime */ SET_UINT64(buf, 40, file_stat.st_size); /* EndOfFile */ SET_UINT64(buf, 48, file_stat.st_size); /* AllocationSize */ SET_UINT32(buf, 56, attr); /* FileAttributes */ SET_UINT32(buf, 64, 0); /* EaSize */ len = freerdp_set_wstr(buf + 68, size - 68, pdirent->d_name, strlen(pdirent->d_name)); SET_UINT32(buf, 60, len); /* FileNameLength */ size = 68 + len; break; default: LLOGLN(0, ("disk_query_directory: invalid info class")); status = RD_STATUS_NOT_SUPPORTED; break; } irp->outputBuffer = buf; irp->outputBufferLength = size; return status; }
status_t internal_path_for_path(char* referencePath, size_t referencePathSize, const char* dependency, const char* architecture, path_base_directory baseDirectory, const char* subPath, uint32 flags, char* pathBuffer, size_t bufferSize) { if (strcmp(architecture, __get_primary_architecture()) == 0) architecture = NULL; // resolve dependency char packageName[B_FILE_NAME_LENGTH]; // Temporarily used here, permanently used below where // B_FIND_PATH_PACKAGE_PATH is handled. if (dependency != NULL) { // get the versioned package name status_t error = get_file_attribute(referencePath, "SYS:PACKAGE", packageName, sizeof(packageName)); if (error != B_OK) return error; // normalize the dependency name char normalizedDependency[B_FILE_NAME_LENGTH]; error = normalize_dependency(dependency, normalizedDependency, sizeof(normalizedDependency)); if (error != B_OK) return error; // Compute the path of the dependency symlink. This will yield the // installation location path when normalized. if (snprintf(referencePath, referencePathSize, kSystemPackageLinksDirectory "/%s/%s", packageName, normalizedDependency) >= (ssize_t)referencePathSize) { return B_BUFFER_OVERFLOW; } } // handle B_FIND_PATH_IMAGE_PATH if (baseDirectory == B_FIND_PATH_IMAGE_PATH) return copy_path(referencePath, pathBuffer, bufferSize); // Handle B_FIND_PATH_PACKAGE_PATH: get the package file name and // simply adjust our arguments to look the package file up in the packages // directory. if (baseDirectory == B_FIND_PATH_PACKAGE_PATH) { status_t error = get_file_attribute(referencePath, "SYS:PACKAGE_FILE", packageName, sizeof(packageName)); if (error != B_OK) return error; dependency = NULL; subPath = packageName; baseDirectory = B_FIND_PATH_PACKAGES_DIRECTORY; flags = B_FIND_PATH_EXISTING_ONLY; } // normalize status_t error = normalize_path(referencePath, referencePath, referencePathSize); if (error != B_OK) return error; // get the installation location InstallationLocations* installationLocations = InstallationLocations::Get(); MethodDeleter<InstallationLocations> installationLocationsDeleter( installationLocations, &InstallationLocations::Put); size_t installationLocationIndex; const char* installationLocation = installationLocations->LocationFor( referencePath, installationLocationIndex); if (installationLocation == NULL) return B_ENTRY_NOT_FOUND; // get base dir and process the path const char* relativePath = get_relative_directory_path( installationLocationIndex, baseDirectory); if (relativePath == NULL) return B_BAD_VALUE; ssize_t pathSize = process_path(installationLocation, architecture, relativePath, subPath, flags, pathBuffer, bufferSize); if (pathSize <= 0) return pathSize == 0 ? B_ENTRY_NOT_FOUND : pathSize; return B_OK; }