Ejemplo n.º 1
0
posix_errno_t efile_read_info(const efile_path_t *path, int follow_links, efile_fileinfo_t *result) {
    BY_HANDLE_FILE_INFORMATION native_file_info;
    DWORD attributes;
    int is_link;

    sys_memset(&native_file_info, 0, sizeof(native_file_info));
    is_link = 0;

    attributes = GetFileAttributesW((WCHAR*)path->data);

    if(attributes == INVALID_FILE_ATTRIBUTES) {
        DWORD last_error = GetLastError();

        /* Querying a network share root fails with ERROR_BAD_NETPATH, so we'll
         * fake it as a directory just like local roots. */
        if(!is_path_root(path) || last_error != ERROR_BAD_NETPATH) {
            return windows_to_posix_errno(last_error);
        }

        attributes = FILE_ATTRIBUTE_DIRECTORY;
    } else if(is_path_root(path)) {
        /* Local (or mounted) roots can be queried with GetFileAttributesW but
         * lack support for GetFileInformationByHandle, so we'll skip that
         * part. */
    } else {
        HANDLE handle;

        if(attributes & FILE_ATTRIBUTE_REPARSE_POINT) {
            is_link = is_name_surrogate(path);
        }

        if(follow_links && is_link) {
            posix_errno_t posix_errno;
            efile_path_t resolved_path;

            posix_errno = internal_read_link(path, &resolved_path);

            if(posix_errno != 0) {
                return posix_errno;
            }

            return efile_read_info(&resolved_path, 0, result);
        }

        handle = CreateFileW((const WCHAR*)path->data, GENERIC_READ,
            FILE_SHARE_FLAGS, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS,
            NULL);

        /* The old driver never cared whether this succeeded. */
        if(handle != INVALID_HANDLE_VALUE) {
            GetFileInformationByHandle(handle, &native_file_info);
            CloseHandle(handle);
        }

        FILETIME_TO_EPOCH(result->m_time, native_file_info.ftLastWriteTime);
        FILETIME_TO_EPOCH(result->a_time, native_file_info.ftLastAccessTime);
        FILETIME_TO_EPOCH(result->c_time, native_file_info.ftCreationTime);

        if(result->m_time == -EPOCH_DIFFERENCE) {
            /* Default to 1970 just like the old driver. */
            result->m_time = 0;
        }

        if(result->a_time == -EPOCH_DIFFERENCE) {
            result->a_time = result->m_time;
        }

        if(result->c_time == -EPOCH_DIFFERENCE) {
            result->c_time = result->m_time;
        }
    }

    if(is_link) {
        result->type = EFILE_FILETYPE_SYMLINK;
        /* This should be _S_IFLNK, but the old driver always set
         * non-directories to _S_IFREG. */
        result->mode |= _S_IFREG;
    } else if(attributes & FILE_ATTRIBUTE_DIRECTORY) {
        result->type = EFILE_FILETYPE_DIRECTORY;
        result->mode |= _S_IFDIR | _S_IEXEC;
    } else {
        if(is_executable_file(path)) {
            result->mode |= _S_IEXEC;
        }

        result->type = EFILE_FILETYPE_REGULAR;
        result->mode |= _S_IFREG;
    }

    if(!(attributes & FILE_ATTRIBUTE_READONLY)) {
        result->access = EFILE_ACCESS_READ | EFILE_ACCESS_WRITE;
        result->mode |= _S_IREAD | _S_IWRITE;
    } else {
        result->access = EFILE_ACCESS_READ;
        result->mode |= _S_IREAD;
    }

    /* Propagate user mode-bits to group/other fields */
    result->mode |= (result->mode & 0700) >> 3;
    result->mode |= (result->mode & 0700) >> 6;

    result->size =
        ((Uint64)native_file_info.nFileSizeHigh << 32ull) |
        (Uint64)native_file_info.nFileSizeLow;

    result->links = MAX(1, native_file_info.nNumberOfLinks);

    result->major_device = get_drive_number(path);
    result->minor_device = 0;
    result->inode = 0;
    result->uid = 0;
    result->gid = 0;

    return 0;
}
Ejemplo n.º 2
0
int which_main(int argc, char **argv)
{
	int status;
	size_t i, count;
	char *path_list;

	if (argc <= 1 || **(argv + 1) == '-') {
		bb_show_usage();
	}
	argc--;

	path_list = getenv("PATH");
	if (path_list != NULL) {
		size_t path_len = strlen(path_list);
		char *new_list = NULL;
		count = 1;

		for (i = 0; i <= path_len; i++) {
			char *this_i = &path_list[i];
			if (*this_i == ':') {
				/* ^::[^:] == \.: */
				if (!i && (*(this_i + 1) == ':')) {
					*this_i = '.';
					continue;
				}
				*this_i = 0;
				count++;
				/* ^:[^:] == \.0 and [^:]::[^:] == 0\.0 and [^:]:$ == 0\.0 */
				if (!i || (*(this_i + 1) == ':') || (i == path_len-1)) {
					new_list = xrealloc(new_list, path_len += 1);
					if (i) {
						memmove(&new_list[i+2], &path_list[i+1], path_len-i);
						new_list[i+1] = '.';
						memmove(new_list, path_list, i);
					} else {
						memmove(&new_list[i+1], &path_list[i], path_len-i);
						new_list[i] = '.';
					}
					path_list = new_list;
				}
			}
		}
	} else {
		path_list = "/bin\0/sbin\0/usr/bin\0/usr/sbin\0/usr/local/bin";
		count = 5;
	}

	status = EXIT_SUCCESS;
	while (argc-- > 0) {
		struct stat stat_b;
		char *buf;
		char *path_n;
		int found = 0;

		argv++;
		path_n = path_list;
		buf = *argv;

		/* if filename is either absolute or contains slashes,
		 * stat it */
		if (strchr(buf, '/') != NULL && is_executable_file(buf, &stat_b)) {
			found++;
		} else {
			/* Couldn't access file and file doesn't contain slashes */
			for (i = 0; i < count; i++) {
				buf = concat_path_file(path_n, *argv);
				if (is_executable_file(buf, &stat_b)) {
					found++;
					break;
				}
				free(buf);
				path_n += (strlen(path_n) + 1);
			}
		}
		if (found) {
			puts(buf);
		} else {
			status = EXIT_FAILURE;
		}
	}
	bb_fflush_stdout_and_exit(status);
}