| /* GLib testing framework examples and tests |
| * Copyright (C) 2008 Red Hat, Inc. |
| * Authors: Tomas Bzatek <tbzatek@redhat.com> |
| * |
| * This work is provided "as is"; redistribution and modification |
| * in whole or in part, in any medium, physical or electronic is |
| * permitted without restriction. |
| * |
| * This work is distributed in the hope that it will be useful, |
| * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| * |
| * In no event shall the authors or contributors be liable for any |
| * direct, indirect, incidental, special, exemplary, or consequential |
| * damages (including, but not limited to, procurement of substitute |
| * goods or services; loss of use, data, or profits; or business |
| * interruption) however caused and on any theory of liability, whether |
| * in contract, strict liability, or tort (including negligence or |
| * otherwise) arising in any way out of the use of this software, even |
| * if advised of the possibility of such damage. |
| */ |
| |
| #include "config.h" |
| |
| #include <glib/glib.h> |
| #include <gio/gio.h> |
| #include <stdlib.h> |
| #include <string.h> |
| #ifdef G_OS_WIN32 |
| #include <stdio.h> |
| #include <glib/gstdio.h> |
| #include <windows.h> |
| #include <shlobj.h> |
| #include <io.h> /* for _get_osfhandle */ |
| #endif |
| |
| #define TEST_NAME "Prilis zlutoucky kun" |
| #define TEST_DISPLAY_NAME "UTF-8 p\xc5\x99\xc3\xadli\xc5\xa1 \xc5\xbelu\xc5\xa5ou\xc4\x8dk\xc3\xbd k\xc5\xaf\xc5\x88" |
| #define TEST_SIZE 0xFFFFFFF0 |
| |
| static void |
| test_assigned_values (GFileInfo *info) |
| { |
| const char *name, *display_name, *mistake; |
| guint64 size; |
| GFileType type; |
| |
| /* Test for attributes presence */ |
| g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_NAME) == TRUE); |
| g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME) == TRUE); |
| g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE) == TRUE); |
| g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME) == FALSE); |
| |
| /* Retrieve data back and compare */ |
| |
| name = g_file_info_get_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME); |
| display_name = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME); |
| mistake = g_file_info_get_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_COPY_NAME); |
| size = g_file_info_get_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE); |
| type = g_file_info_get_file_type (info); |
| |
| g_assert_cmpstr (name, ==, TEST_NAME); |
| g_assert_cmpstr (display_name, ==, TEST_DISPLAY_NAME); |
| g_assert (mistake == NULL); |
| g_assert_cmpint (size, ==, TEST_SIZE); |
| g_assert_cmpstr (name, ==, g_file_info_get_name (info)); |
| g_assert_cmpstr (display_name, ==, g_file_info_get_display_name (info)); |
| g_assert_cmpint (size, ==, g_file_info_get_size (info) ); |
| g_assert_cmpint (type, ==, G_FILE_TYPE_DIRECTORY); |
| } |
| |
| |
| |
| static void |
| test_g_file_info (void) |
| { |
| GFileInfo *info; |
| GFileInfo *info_dup; |
| GFileInfo *info_copy; |
| char **attr_list; |
| GFileAttributeMatcher *matcher; |
| |
| info = g_file_info_new (); |
| |
| /* Test for empty instance */ |
| attr_list = g_file_info_list_attributes (info, NULL); |
| g_assert (attr_list != NULL); |
| g_assert (*attr_list == NULL); |
| g_strfreev (attr_list); |
| |
| g_file_info_set_attribute_byte_string (info, G_FILE_ATTRIBUTE_STANDARD_NAME, TEST_NAME); |
| g_file_info_set_attribute_string (info, G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME, TEST_DISPLAY_NAME); |
| g_file_info_set_attribute_uint64 (info, G_FILE_ATTRIBUTE_STANDARD_SIZE, TEST_SIZE); |
| g_file_info_set_file_type (info, G_FILE_TYPE_DIRECTORY); |
| |
| /* The attr list should not be empty now */ |
| attr_list = g_file_info_list_attributes (info, NULL); |
| g_assert (attr_list != NULL); |
| g_assert (*attr_list != NULL); |
| g_strfreev (attr_list); |
| |
| test_assigned_values (info); |
| |
| /* Test dups */ |
| info_dup = g_file_info_dup (info); |
| g_assert (info_dup != NULL); |
| test_assigned_values (info_dup); |
| |
| info_copy = g_file_info_new (); |
| g_file_info_copy_into (info_dup, info_copy); |
| g_assert (info_copy != NULL); |
| test_assigned_values (info_copy); |
| |
| /* Test remove attribute */ |
| g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER) == FALSE); |
| g_file_info_set_attribute_int32 (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER, 10); |
| g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER) == TRUE); |
| |
| g_assert (g_file_info_get_attribute_type (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER) == G_FILE_ATTRIBUTE_TYPE_INT32); |
| g_assert (g_file_info_get_attribute_status (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER) != G_FILE_ATTRIBUTE_STATUS_ERROR_SETTING); |
| |
| g_file_info_remove_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER); |
| g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER) == FALSE); |
| g_assert (g_file_info_get_attribute_type (info, G_FILE_ATTRIBUTE_STANDARD_SORT_ORDER) == G_FILE_ATTRIBUTE_TYPE_INVALID); |
| |
| matcher = g_file_attribute_matcher_new (G_FILE_ATTRIBUTE_STANDARD_NAME "," |
| G_FILE_ATTRIBUTE_STANDARD_DISPLAY_NAME); |
| |
| g_assert (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_NAME) == TRUE); |
| g_assert (g_file_attribute_matcher_matches_only (matcher, G_FILE_ATTRIBUTE_STANDARD_NAME) == FALSE); |
| g_assert (g_file_attribute_matcher_matches (matcher, G_FILE_ATTRIBUTE_STANDARD_SIZE) == FALSE); |
| |
| g_file_info_set_attribute_mask (info, matcher); |
| g_file_attribute_matcher_unref (matcher); |
| |
| g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_SIZE) == FALSE); |
| g_assert (g_file_info_has_attribute (info, G_FILE_ATTRIBUTE_STANDARD_NAME) == TRUE); |
| |
| g_object_unref (info); |
| g_object_unref (info_dup); |
| g_object_unref (info_copy); |
| } |
| |
| #ifdef G_OS_WIN32 |
| static void |
| test_internal_enhanced_stdio (void) |
| { |
| char *p0, *p1, *ps; |
| gboolean try_sparse; |
| gchar *tmp_dir_root; |
| wchar_t *tmp_dir_root_w; |
| gchar *c; |
| DWORD fsflags; |
| FILE *f; |
| SYSTEMTIME st; |
| FILETIME ft; |
| HANDLE h; |
| GStatBuf statbuf_p0, statbuf_p1, statbuf_ps; |
| GFile *gf_p0, *gf_p1, *gf_ps; |
| GFileInfo *fi_p0, *fi_p1, *fi_ps; |
| guint64 size_p0, alsize_p0, size_ps, alsize_ps; |
| const gchar *id_p0; |
| const gchar *id_p1; |
| volatile guint64 time_p0; |
| gchar *tmp_dir; |
| wchar_t *programdata_dir_w; |
| wchar_t *users_dir_w; |
| static const GUID folder_id_programdata = |
| { 0x62AB5D82, 0xFDC1, 0x4DC3, { 0xA9, 0xDD, 0x07, 0x0D, 0x1D, 0x49, 0x5D, 0x97 } }; |
| static const GUID folder_id_users = |
| { 0x0762D272, 0xC50A, 0x4BB0, { 0xA3, 0x82, 0x69, 0x7D, 0xCD, 0x72, 0x9B, 0x80 } }; |
| |
| programdata_dir_w = NULL; |
| SHGetKnownFolderPath (&folder_id_programdata, 0, NULL, &programdata_dir_w); |
| |
| users_dir_w = NULL; |
| SHGetKnownFolderPath (&folder_id_users, 0, NULL, &users_dir_w); |
| |
| if (programdata_dir_w != NULL && users_dir_w != NULL) |
| { |
| gchar *programdata; |
| gchar *users_dir; |
| gchar *allusers; |
| gchar *commondata; |
| GFile *gf_programdata, *gf_allusers, *gf_commondata; |
| GFileInfo *fi_programdata, *fi_allusers, *fi_allusers_target, *fi_commondata, *fi_commondata_target; |
| GFileType ft_allusers; |
| GFileType ft_allusers_target; |
| GFileType ft_programdata; |
| GFileType ft_commondata; |
| gboolean allusers_is_symlink; |
| gboolean commondata_is_symlink; |
| gboolean commondata_is_mount_point; |
| guint32 allusers_reparse_tag; |
| guint32 commondata_reparse_tag; |
| const gchar *id_allusers; |
| const gchar *id_allusers_target; |
| const gchar *id_commondata_target; |
| const gchar *id_programdata; |
| const gchar *allusers_target; |
| const gchar *commondata_target; |
| |
| /* C:/ProgramData */ |
| programdata = g_utf16_to_utf8 (programdata_dir_w, -1, NULL, NULL, NULL); |
| g_assert_nonnull (programdata); |
| /* C:/Users */ |
| users_dir = g_utf16_to_utf8 (users_dir_w, -1, NULL, NULL, NULL); |
| g_assert_nonnull (users_dir); |
| /* "C:/Users/All Users" is a known directory symlink |
| * for "C:/ProgramData". |
| */ |
| allusers = g_build_filename (users_dir, "All Users", NULL); |
| |
| /* "C:/Users/All Users/Application Data" is a known |
| * junction for "C:/ProgramData" |
| */ |
| commondata = g_build_filename (allusers, "Application Data", NULL); |
| |
| /* We don't test g_stat() and g_lstat() on these directories, |
| * because it is pointless - there's no way to tell that these |
| * functions behave correctly in this case |
| * (st_ino is useless, so we can't tell apart g_stat() and g_lstat() |
| * results; st_mode is also useless as it does not support S_ISLNK; |
| * and these directories have no interesting properties other |
| * than [not] being symlinks). |
| */ |
| gf_programdata = g_file_new_for_path (programdata); |
| gf_allusers = g_file_new_for_path (allusers); |
| gf_commondata = g_file_new_for_path (commondata); |
| |
| fi_programdata = g_file_query_info (gf_programdata, |
| G_FILE_ATTRIBUTE_ID_FILE "," |
| G_FILE_ATTRIBUTE_STANDARD_TYPE, |
| G_FILE_QUERY_INFO_NONE, |
| NULL, NULL); |
| |
| fi_allusers_target = g_file_query_info (gf_allusers, |
| G_FILE_ATTRIBUTE_ID_FILE "," |
| G_FILE_ATTRIBUTE_STANDARD_TYPE, |
| G_FILE_QUERY_INFO_NONE, |
| NULL, NULL); |
| |
| fi_allusers = g_file_query_info (gf_allusers, |
| G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET "," |
| G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK "," |
| G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG "," |
| G_FILE_ATTRIBUTE_ID_FILE "," |
| G_FILE_ATTRIBUTE_STANDARD_TYPE, |
| G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, |
| NULL, NULL); |
| |
| fi_commondata = g_file_query_info (gf_commondata, |
| G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET "," |
| G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK "," |
| G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT "," |
| G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG "," |
| G_FILE_ATTRIBUTE_ID_FILE "," |
| G_FILE_ATTRIBUTE_STANDARD_TYPE, |
| G_FILE_QUERY_INFO_NOFOLLOW_SYMLINKS, |
| NULL, NULL); |
| |
| fi_commondata_target = g_file_query_info (gf_commondata, |
| G_FILE_ATTRIBUTE_ID_FILE "," |
| G_FILE_ATTRIBUTE_STANDARD_TYPE, |
| G_FILE_QUERY_INFO_NONE, |
| NULL, NULL); |
| |
| g_assert_true (g_file_info_has_attribute (fi_programdata, G_FILE_ATTRIBUTE_ID_FILE)); |
| g_assert_true (g_file_info_has_attribute (fi_programdata, G_FILE_ATTRIBUTE_STANDARD_TYPE)); |
| |
| g_assert_true (g_file_info_has_attribute (fi_allusers_target, G_FILE_ATTRIBUTE_ID_FILE)); |
| g_assert_true (g_file_info_has_attribute (fi_allusers_target, G_FILE_ATTRIBUTE_STANDARD_TYPE)); |
| g_assert_true (g_file_info_has_attribute (fi_commondata_target, G_FILE_ATTRIBUTE_ID_FILE)); |
| g_assert_true (g_file_info_has_attribute (fi_commondata_target, G_FILE_ATTRIBUTE_STANDARD_TYPE)); |
| |
| g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_ID_FILE)); |
| g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_TYPE)); |
| g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK)); |
| g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG)); |
| g_assert_true (g_file_info_has_attribute (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET)); |
| |
| g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_ID_FILE)); |
| g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_TYPE)); |
| g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK)); |
| g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT)); |
| g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG)); |
| g_assert_true (g_file_info_has_attribute (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_SYMLINK_TARGET)); |
| |
| ft_allusers = g_file_info_get_file_type (fi_allusers); |
| ft_allusers_target = g_file_info_get_file_type (fi_allusers_target); |
| ft_programdata = g_file_info_get_file_type (fi_programdata); |
| ft_commondata = g_file_info_get_file_type (fi_commondata); |
| |
| g_assert_cmpint (ft_allusers, ==, G_FILE_TYPE_SYMBOLIC_LINK); |
| g_assert_cmpint (ft_allusers_target, ==, G_FILE_TYPE_DIRECTORY); |
| g_assert_cmpint (ft_programdata, ==, G_FILE_TYPE_DIRECTORY); |
| g_assert_cmpint (ft_commondata, ==, G_FILE_TYPE_SYMBOLIC_LINK); |
| |
| allusers_is_symlink = g_file_info_get_attribute_boolean (fi_allusers, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK); |
| allusers_reparse_tag = g_file_info_get_attribute_uint32 (fi_allusers, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG); |
| commondata_is_symlink = g_file_info_get_attribute_boolean (fi_commondata, G_FILE_ATTRIBUTE_STANDARD_IS_SYMLINK); |
| commondata_is_mount_point = g_file_info_get_attribute_boolean (fi_commondata, G_FILE_ATTRIBUTE_DOS_IS_MOUNTPOINT); |
| commondata_reparse_tag = g_file_info_get_attribute_uint32 (fi_commondata, G_FILE_ATTRIBUTE_DOS_REPARSE_POINT_TAG); |
| |
| g_assert_true (allusers_is_symlink); |
| g_assert_cmpuint (allusers_reparse_tag, ==, IO_REPARSE_TAG_SYMLINK); |
| g_assert_true (commondata_is_symlink); |
| g_assert_true (commondata_is_mount_point); |
| g_assert_cmpuint (commondata_reparse_tag, ==, IO_REPARSE_TAG_MOUNT_POINT); |
| |
| id_allusers = g_file_info_get_attribute_string (fi_allusers, G_FILE_ATTRIBUTE_ID_FILE); |
| id_allusers_target = g_file_info_get_attribute_string (fi_allusers_target, G_FILE_ATTRIBUTE_ID_FILE); |
| id_commondata_target = g_file_info_get_attribute_string (fi_commondata_target, G_FILE_ATTRIBUTE_ID_FILE); |
| id_programdata = g_file_info_get_attribute_string (fi_programdata, G_FILE_ATTRIBUTE_ID_FILE); |
| |
| g_assert_cmpstr (id_allusers_target, ==, id_programdata); |
| g_assert_cmpstr (id_commondata_target, ==, id_programdata); |
| g_assert_cmpstr (id_allusers, !=, id_programdata); |
| |
| allusers_target = g_file_info_get_symlink_target (fi_allusers); |
| |
| g_assert_true (g_str_has_suffix (allusers_target, "ProgramData")); |
| |
| commondata_target = g_file_info_get_symlink_target (fi_commondata); |
| |
| g_assert_true (g_str_has_suffix (commondata_target, "ProgramData")); |
| |
| g_object_unref (fi_allusers); |
| g_object_unref (fi_allusers_target); |
| g_object_unref (fi_commondata); |
| g_object_unref (fi_commondata_target); |
| g_object_unref (fi_programdata); |
| g_object_unref (gf_allusers); |
| g_object_unref (gf_commondata); |
| g_object_unref (gf_programdata); |
| |
| g_free (allusers); |
| g_free (commondata); |
| g_free (users_dir); |
| g_free (programdata); |
| } |
| |
| if (programdata_dir_w) |
| CoTaskMemFree (programdata_dir_w); |
| |
| if (users_dir_w) |
| CoTaskMemFree (users_dir_w); |
| |
| tmp_dir = g_dir_make_tmp ("glib_stdio_testXXXXXX", NULL); |
| g_assert_nonnull (tmp_dir); |
| |
| /* Technically, this isn't necessary - we already assume NTFS, because of |
| * symlink support, and NTFS also supports sparse files. Still, given |
| * the amount of unusual I/O APIs called in this test, checking for |
| * sparse file support of the filesystem where temp directory is |
| * doesn't seem to be out of place. |
| */ |
| try_sparse = FALSE; |
| tmp_dir_root = g_strdup (tmp_dir); |
| /* We need "C:\\" or "C:/", with a trailing [back]slash */ |
| for (c = tmp_dir_root; c && c[0] && c[1]; c++) |
| if (c[0] == ':') |
| { |
| c[2] = '\0'; |
| break; |
| } |
| tmp_dir_root_w = g_utf8_to_utf16 (tmp_dir_root, -1, NULL, NULL, NULL); |
| g_assert_nonnull (tmp_dir_root_w); |
| g_free (tmp_dir_root); |
| g_assert_true (GetVolumeInformationW (tmp_dir_root_w, NULL, 0, NULL, NULL, &fsflags, NULL, 0)); |
| g_free (tmp_dir_root_w); |
| try_sparse = (fsflags & FILE_SUPPORTS_SPARSE_FILES) == FILE_SUPPORTS_SPARSE_FILES; |
| |
| p0 = g_build_filename (tmp_dir, "zool", NULL); |
| p1 = g_build_filename (tmp_dir, "looz", NULL); |
| ps = g_build_filename (tmp_dir, "sparse", NULL); |
| |
| if (try_sparse) |
| { |
| FILE_SET_SPARSE_BUFFER ssb; |
| FILE_ZERO_DATA_INFORMATION zdi; |
| |
| g_remove (ps); |
| |
| f = g_fopen (ps, "wb"); |
| g_assert_nonnull (f); |
| |
| h = (HANDLE) _get_osfhandle (fileno (f)); |
| g_assert_cmpuint ((guintptr) h, !=, (guintptr) INVALID_HANDLE_VALUE); |
| |
| ssb.SetSparse = TRUE; |
| g_assert_true (DeviceIoControl (h, |
| FSCTL_SET_SPARSE, |
| &ssb, sizeof (ssb), |
| NULL, 0, NULL, NULL)); |
| |
| /* Make it a sparse file that starts with 4GBs of zeros */ |
| zdi.FileOffset.QuadPart = 0; |
| zdi.BeyondFinalZero.QuadPart = 0xFFFFFFFFULL + 1; |
| g_assert_true (DeviceIoControl (h, |
| FSCTL_SET_ZERO_DATA, |
| &zdi, sizeof (zdi), |
| NULL, 0, NULL, NULL)); |
| |
| /* Let's not keep this seemingly 4GB monster around |
| * longer than we absolutely need to. Do all operations |
| * without assertions, then remove the file immediately. |
| */ |
| _fseeki64 (f, 0xFFFFFFFFULL, SEEK_SET); |
| fprintf (f, "Hello 4GB World!"); |
| fflush (f); |
| fclose (f); |
| |
| memset (&statbuf_ps, 0, sizeof (statbuf_ps)); |
| |
| g_stat (ps, &statbuf_ps); |
| |
| gf_ps = g_file_new_for_path (ps); |
| |
| fi_ps = g_file_query_info (gf_ps, |
| G_FILE_ATTRIBUTE_STANDARD_SIZE "," |
| G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE, |
| G_FILE_QUERY_INFO_NONE, |
| NULL, NULL); |
| |
| g_remove (ps); |
| |
| g_assert_true (g_file_info_has_attribute (fi_ps, G_FILE_ATTRIBUTE_STANDARD_SIZE)); |
| g_assert_true (g_file_info_has_attribute (fi_ps, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE)); |
| |
| size_ps = g_file_info_get_attribute_uint64 (fi_ps, G_FILE_ATTRIBUTE_STANDARD_SIZE); |
| alsize_ps = g_file_info_get_attribute_uint64 (fi_ps, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE); |
| |
| /* allocated size should small (usually - size of the FS cluster, |
| * let's assume it's less than 1 gigabyte), |
| * size should be more than 4 gigabytes, |
| * st_size should not exceed its 0xFFFFFFFF 32-bit limit, |
| * and should be nonzero (this also detects a failed g_stat() earlier). |
| */ |
| g_assert_cmpuint (alsize_ps, <, 0x40000000); |
| g_assert_cmpuint (size_ps, >, G_GUINT64_CONSTANT (0xFFFFFFFF)); |
| g_assert_cmpuint (statbuf_ps.st_size, >, 0); |
| g_assert_cmpuint (statbuf_ps.st_size, <=, 0xFFFFFFFF); |
| |
| g_object_unref (fi_ps); |
| g_object_unref (gf_ps); |
| } |
| |
| /* Wa-a-ay past 02/07/2106 @ 6:28am (UTC), |
| * which is the date corresponding to 0xFFFFFFFF + 1. |
| * This is easier to check than Y2038 (0x80000000 + 1), |
| * since there's no need to worry about signedness this way. |
| */ |
| st.wYear = 2106; |
| st.wMonth = 2; |
| st.wDay = 9; |
| st.wHour = 0; |
| st.wMinute = 0; |
| st.wSecond = 0; |
| st.wMilliseconds = 0; |
| |
| g_assert_true (SystemTimeToFileTime (&st, &ft)); |
| |
| f = g_fopen (p0, "w"); |
| g_assert_nonnull (f); |
| |
| h = (HANDLE) _get_osfhandle (fileno (f)); |
| g_assert_cmpuint ((guintptr) h, !=, (guintptr) INVALID_HANDLE_VALUE); |
| |
| fprintf (f, "1"); |
| fflush (f); |
| |
| g_assert_true (SetFileTime (h, &ft, &ft, &ft)); |
| |
| fclose (f); |
| |
| f = g_fopen (p1, "w"); |
| g_assert_nonnull (f); |
| |
| fclose (f); |
| |
| memset (&statbuf_p0, 0, sizeof (statbuf_p0)); |
| memset (&statbuf_p1, 0, sizeof (statbuf_p1)); |
| |
| g_assert_cmpint (g_stat (p0, &statbuf_p0), ==, 0); |
| g_assert_cmpint (g_stat (p1, &statbuf_p1), ==, 0); |
| |
| gf_p0 = g_file_new_for_path (p0); |
| gf_p1 = g_file_new_for_path (p1); |
| |
| fi_p0 = g_file_query_info (gf_p0, |
| G_FILE_ATTRIBUTE_STANDARD_SIZE "," |
| G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE "," |
| G_FILE_ATTRIBUTE_ID_FILE "," |
| G_FILE_ATTRIBUTE_TIME_MODIFIED, |
| G_FILE_QUERY_INFO_NONE, |
| NULL, NULL); |
| |
| fi_p1 = g_file_query_info (gf_p1, |
| G_FILE_ATTRIBUTE_STANDARD_SIZE "," |
| G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE "," |
| G_FILE_ATTRIBUTE_ID_FILE "," |
| G_FILE_ATTRIBUTE_TIME_MODIFIED, |
| G_FILE_QUERY_INFO_NONE, |
| NULL, NULL); |
| |
| g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_STANDARD_SIZE)); |
| g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE)); |
| g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_ID_FILE)); |
| g_assert_true (g_file_info_has_attribute (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED)); |
| |
| g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_SIZE)); |
| g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE)); |
| g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_ID_FILE)); |
| g_assert_true (g_file_info_has_attribute (fi_p1, G_FILE_ATTRIBUTE_TIME_MODIFIED)); |
| |
| size_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_SIZE); |
| alsize_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_STANDARD_ALLOCATED_SIZE); |
| |
| /* size should be 1, allocated size should be something else |
| * (could be 0 or the size of the FS cluster, but never 1). |
| */ |
| g_assert_cmpuint (size_p0, ==, statbuf_p0.st_size); |
| g_assert_cmpuint (size_p0, ==, 1); |
| g_assert_cmpuint (alsize_p0, !=, size_p0); |
| |
| id_p0 = g_file_info_get_attribute_string (fi_p0, G_FILE_ATTRIBUTE_ID_FILE); |
| id_p1 = g_file_info_get_attribute_string (fi_p1, G_FILE_ATTRIBUTE_ID_FILE); |
| |
| /* st_ino from W32 stat() is useless for file identification. |
| * It will be either 0, or it will be the same for both files. |
| */ |
| g_assert_cmpint (statbuf_p0.st_ino, ==, statbuf_p1.st_ino); |
| g_assert_cmpstr (id_p0, !=, id_p1); |
| |
| time_p0 = g_file_info_get_attribute_uint64 (fi_p0, G_FILE_ATTRIBUTE_TIME_MODIFIED); |
| |
| /* Check that GFileInfo doesn't suffer from Y2106 problem. |
| * Don't check stat(), as its contents may vary depending on |
| * the host platform architecture |
| * (time fields are 32-bit on 32-bit Windows, |
| * and 64-bit on 64-bit Windows, usually), |
| * so it *can* pass this test in some cases. |
| */ |
| g_assert_cmpuint (time_p0, >, G_GUINT64_CONSTANT (0xFFFFFFFF)); |
| |
| g_object_unref (fi_p0); |
| g_object_unref (fi_p1); |
| g_object_unref (gf_p0); |
| g_object_unref (gf_p1); |
| g_remove (p0); |
| g_remove (p1); |
| g_free (p0); |
| g_free (p1); |
| g_rmdir (tmp_dir); |
| } |
| #endif |
| |
| |
| int |
| main (int argc, |
| char *argv[]) |
| { |
| g_test_init (&argc, &argv, NULL); |
| |
| g_test_add_func ("/g-file-info/test_g_file_info", test_g_file_info); |
| #ifdef G_OS_WIN32 |
| g_test_add_func ("/g-file-info/internal-enhanced-stdio", test_internal_enhanced_stdio); |
| #endif |
| |
| return g_test_run(); |
| } |