📄 syscalls.cc
字号:
} if (real_b.exists ()) { syscall_printf ("file '%s' exists?", (char *) real_b); set_errno (EEXIST); goto done; } if (real_b[strlen (real_b) - 1] == '.') { syscall_printf ("trailing dot, bailing out"); set_errno (EINVAL); goto done; } /* Try to make hard link first on Windows NT */ if (wincap.has_hard_links ()) { if (CreateHardLinkA (real_b, real_a, NULL)) { res = 0; goto done; } HANDLE hFileSource; WIN32_STREAM_ID StreamId; DWORD dwBytesWritten; LPVOID lpContext; DWORD cbPathLen; DWORD StreamSize; WCHAR wbuf[MAX_PATH]; BOOL bSuccess; hFileSource = CreateFile (real_a, FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ | FILE_SHARE_WRITE /*| FILE_SHARE_DELETE*/, &sec_none_nih, // sa OPEN_EXISTING, 0, NULL); if (hFileSource == INVALID_HANDLE_VALUE) { syscall_printf ("cannot open source, %E"); goto docopy; } cbPathLen = sys_mbstowcs (wbuf, real_b, MAX_PATH) * sizeof (WCHAR); StreamId.dwStreamId = BACKUP_LINK; StreamId.dwStreamAttributes = 0; StreamId.dwStreamNameSize = 0; StreamId.Size.HighPart = 0; StreamId.Size.LowPart = cbPathLen; StreamSize = sizeof (WIN32_STREAM_ID) - sizeof (WCHAR**) + StreamId.dwStreamNameSize; lpContext = NULL; /* Write the WIN32_STREAM_ID */ bSuccess = BackupWrite ( hFileSource, (LPBYTE) &StreamId, // buffer to write StreamSize, // number of bytes to write &dwBytesWritten, FALSE, // don't abort yet FALSE, // don't process security &lpContext); if (bSuccess) { /* write the buffer containing the path */ /* FIXME: BackupWrite sometimes traps if linkname is invalid. Need to handle. */ bSuccess = BackupWrite ( hFileSource, (LPBYTE) wbuf, // buffer to write cbPathLen, // number of bytes to write &dwBytesWritten, FALSE, // don't abort yet FALSE, // don't process security &lpContext ); if (!bSuccess) syscall_printf ("cannot write linkname, %E"); /* Free context */ BackupWrite ( hFileSource, NULL, // buffer to write 0, // number of bytes to write &dwBytesWritten, TRUE, // abort FALSE, // don't process security &lpContext); } else syscall_printf ("cannot write streamId, %E"); CloseHandle (hFileSource); if (!bSuccess) goto docopy; res = 0; goto done; }docopy: /* do this with a copy */ if (CopyFileA (real_a, real_b, 1)) res = 0; else __seterrno ();done: syscall_printf ("%d = link (%s, %s)", res, a, b); return res;}/* chown: POSIX 5.6.5.1 *//* * chown () is only implemented for Windows NT. Under other operating * systems, it is only a stub that always returns zero. */static intchown_worker (const char *name, unsigned fmode, __uid32_t uid, __gid32_t gid){ int res; if (check_null_empty_str_errno (name)) return -1; if (!wincap.has_security ()) // real chown only works on NT res = 0; // return zero (and do nothing) under Windows 9x else { /* we need Win32 path names because of usage of Win32 API functions */ path_conv win32_path (PC_NONULLEMPTY, name, fmode); if (win32_path.error) { set_errno (win32_path.error); res = -1; goto done; } /* FIXME: This makes chown on a device succeed always. Someday we'll want to actually allow chown to work properly on devices. */ if (win32_path.is_device ()) { res = 0; goto done; } DWORD attrib = 0; if (win32_path.isdir ()) attrib |= S_IFDIR; res = get_file_attribute (win32_path.has_acls (), win32_path.get_win32 (), (int *) &attrib); if (!res) res = set_file_attribute (win32_path.has_acls (), win32_path, uid, gid, attrib); if (res != 0 && (!win32_path.has_acls () || !allow_ntsec)) { /* fake - if not supported, pretend we're like win95 where it just works */ res = 0; } }done: syscall_printf ("%d = %schown (%s,...)", res, (fmode & PC_SYM_NOFOLLOW) ? "l" : "", name); return res;}extern "C" intchown32 (const char * name, __uid32_t uid, __gid32_t gid){ sigframe thisframe (mainthread); return chown_worker (name, PC_SYM_FOLLOW, uid, gid);}extern "C" intchown (const char * name, __uid16_t uid, __gid16_t gid){ sigframe thisframe (mainthread); return chown_worker (name, PC_SYM_FOLLOW, uid16touid32 (uid), gid16togid32 (gid));}extern "C" intlchown32 (const char * name, __uid32_t uid, __gid32_t gid){ sigframe thisframe (mainthread); return chown_worker (name, PC_SYM_NOFOLLOW, uid, gid);}extern "C" intlchown (const char * name, __uid16_t uid, __gid16_t gid){ sigframe thisframe (mainthread); return chown_worker (name, PC_SYM_NOFOLLOW, uid16touid32 (uid), gid16togid32 (gid));}extern "C" intfchown32 (int fd, __uid32_t uid, __gid32_t gid){ sigframe thisframe (mainthread); cygheap_fdget cfd (fd); if (cfd < 0) { syscall_printf ("-1 = fchown (%d,...)", fd); return -1; } const char *path = cfd->get_name (); if (path == NULL) { syscall_printf ("-1 = fchown (%d,...) (no name)", fd); set_errno (ENOSYS); return -1; } syscall_printf ("fchown (%d,...): calling chown_worker (%s,FOLLOW,...)", fd, path); return chown_worker (path, PC_SYM_FOLLOW, uid, gid);}extern "C" intfchown (int fd, __uid16_t uid, __gid16_t gid){ return fchown32 (fd, uid16touid32 (uid), gid16togid32 (gid));}/* umask: POSIX 5.3.3.1 */extern "C" mode_tumask (mode_t mask){ mode_t oldmask; oldmask = cygheap->umask; cygheap->umask = mask & 0777; return oldmask;}/* chmod: POSIX 5.6.4.1 */extern "C" intchmod (const char *path, mode_t mode){ int res = -1; sigframe thisframe (mainthread); path_conv win32_path (path); if (win32_path.error) { set_errno (win32_path.error); goto done; } /* FIXME: This makes chmod on a device succeed always. Someday we'll want to actually allow chmod to work properly on devices. */ if (win32_path.is_device ()) { res = 0; goto done; } if (!win32_path.exists ()) __seterrno (); else { /* temporary erase read only bit, to be able to set file security */ SetFileAttributes (win32_path, (DWORD) win32_path & ~FILE_ATTRIBUTE_READONLY); if (win32_path.isdir ()) mode |= S_IFDIR; if (!set_file_attribute (win32_path.has_acls (), win32_path, ILLEGAL_UID, ILLEGAL_GID, mode) && allow_ntsec) res = 0; /* if the mode we want has any write bits set, we can't be read only. */ if (mode & (S_IWUSR | S_IWGRP | S_IWOTH)) (DWORD) win32_path &= ~FILE_ATTRIBUTE_READONLY; else (DWORD) win32_path |= FILE_ATTRIBUTE_READONLY; if (S_ISLNK (mode) || S_ISSOCK (mode)) (DWORD) win32_path |= FILE_ATTRIBUTE_SYSTEM; if (!SetFileAttributes (win32_path, win32_path)) __seterrno (); else if (!allow_ntsec) /* Correct NTFS security attributes have higher priority */ res = 0; }done: syscall_printf ("%d = chmod (%s, %p)", res, path, mode); return res;}/* fchmod: P96 5.6.4.1 */extern "C" intfchmod (int fd, mode_t mode){ sigframe thisframe (mainthread); cygheap_fdget cfd (fd); if (cfd < 0) { syscall_printf ("-1 = fchmod (%d, 0%o)", fd, mode); return -1; } const char *path = cfd->get_name (); if (path == NULL) { syscall_printf ("-1 = fchmod (%d, 0%o) (no name)", fd, mode); set_errno (ENOSYS); return -1; } syscall_printf ("fchmod (%d, 0%o): calling chmod (%s, 0%o)", fd, mode, path, mode); return chmod (path, mode);}static voidstat64_to_stat32 (struct __stat64 *src, struct __stat32 *dst){ dst->st_dev = ((src->st_dev >> 8) & 0xff00) | (src->st_dev & 0xff); dst->st_ino = src->st_ino; dst->st_mode = src->st_mode; dst->st_nlink = src->st_nlink; dst->st_uid = src->st_uid; dst->st_gid = src->st_gid; dst->st_rdev = ((src->st_rdev >> 8) & 0xff00) | (src->st_rdev & 0xff); dst->st_size = src->st_size; dst->st_atim = src->st_atim; dst->st_mtim = src->st_mtim; dst->st_ctim = src->st_ctim; dst->st_blksize = src->st_blksize; dst->st_blocks = src->st_blocks;}extern "C" intfstat64 (int fd, struct __stat64 *buf){ int res; sigframe thisframe (mainthread); cygheap_fdget cfd (fd); if (cfd < 0) res = -1; else { path_conv pc (cfd->get_win32_name (), PC_SYM_NOFOLLOW); memset (buf, 0, sizeof (struct __stat64)); res = cfd->fstat (buf, &pc); if (!res) { if (!buf->st_ino) buf->st_ino = hash_path_name (0, cfd->get_win32_name ()); if (!buf->st_dev) buf->st_dev = (cfd->get_device () << 16) | cfd->get_unit (); if (!buf->st_rdev) buf->st_rdev = buf->st_dev; } } syscall_printf ("%d = fstat (%d, %p)", res, fd, buf); return res;}extern "C" int_fstat (int fd, struct __stat32 *buf){ struct __stat64 buf64; int ret = fstat64 (fd, &buf64); if (!ret) stat64_to_stat32 (&buf64, buf); return ret;}/* fsync: P96 6.6.1.1 */extern "C" intfsync (int fd){ sigframe thisframe (mainthread); cygheap_fdget cfd (fd); if (cfd < 0) { syscall_printf ("-1 = fsync (%d)", fd); return -1; } if (FlushFileBuffers (cfd->get_handle ()) == 0) { __seterrno (); return -1; } return 0;}/* sync: standards? */extern "C" intsync (){ return 0;}suffix_info stat_suffixes[] ={ suffix_info ("", 1), suffix_info (".exe", 1), suffix_info (NULL)};/* Cygwin internal */int __stdcallstat_worker (const char *name, struct __stat64 *buf, int nofollow, path_conv *pc){ int res = -1; path_conv real_path; fhandler_base *fh = NULL; if (check_null_invalid_struct_errno (buf)) goto done; if (!pc) pc = &real_path; fh = cygheap->fdtab.build_fhandler_from_name (-1, name, NULL, *pc, (nofollow ? PC_SYM_NOFOLLOW : PC_SYM_FOLLOW) | PC_FULL, stat_suffixes); if (pc->error) { debug_printf ("got %d error from build_fhandler_from_name", pc->error); set_errno (pc->error); } else { debug_printf ("(%s, %p, %d, %p), file_attributes %d", name, buf, nofollow, pc, (DWORD) real_path); memset (buf, 0, sizeof (*buf)); res = fh->fstat (buf, pc); if (!res) { if (!buf->st_ino) buf->st_ino = hash_path_name (0, fh->get_win32_name ()); if (!buf->st_dev) buf->st_dev = (fh->get_device () << 16) | fh->get_unit (); if (!buf->st_rdev) buf->st_rdev = buf->st_dev; } } done: if (fh) delete fh; MALLOC_CHECK; syscall_printf ("%d = (%s, %p)", res, name, buf); return res;}extern "C" intstat64 (const char *name, struct __stat64 *buf){ sigframe thisframe (mainthread); syscall_printf ("entering"); return stat_worker (name, buf, 0);}extern "C" int_stat (const char *name, struct __stat32 *buf){ struct __stat64 buf64; int ret = stat64 (name, &buf64); if (!ret) stat64_to_stat32 (&buf64, buf); return ret;}/* lstat: Provided by SVR4 and 4.3+BSD, POSIX? */extern "C" intlstat64 (const char *name, struct __stat64 *buf){ sigframe thisframe (mainthread); syscall_printf ("entering"); return stat_worker (name, buf, 1);}/* lstat: Provided by SVR4 and 4.3+BSD, POSIX? */extern "C" intcygwin_lstat (const char *name, struct __stat32 *buf){ struct __stat64 buf64; int ret = lstat64 (name, &buf64); if (!ret) stat64_to_stat32 (&buf64, buf); return ret;}extern int acl_access (const char *, int);extern "C" intaccess (const char *fn, int flags){ sigframe thisframe (mainthread); // flags were incorrectly specified if (flags & ~(F_OK|R_OK|W_OK|X_OK)) { set_errno (EINVAL); return -1; } if (allow_ntsec) return acl_access (fn, flags); struct __stat64 st; int r = stat_worker (fn, &st, 0); if (r) return -1; r = -1; if (flags & R_OK) { if (st.st_uid == myself->uid) { if (!(st.st_mode & S_IRUSR)) goto done; } else if (st.st_gid == myself->gid) { if (!(st.st_mode & S_IRGRP)) goto done; } else if (!(st.st_mode & S_IROTH)) goto done; } if (flags & W_OK) { if (st.st_uid == myself->uid) { if (!(st.st_mode & S_IWUSR)) goto done; } else if (st.st_gid == myself->gid) { if (!(st.st_mode & S_IWGRP)) goto done; } else if (!(st.st_mode & S_IWOTH)) goto done; } if (flags & X_OK) { if (st.st_uid == myself->uid) { if (!(st.st_mode & S_IXUSR)) goto done; } else if (st.st_gid == myself->gid) { if (!(st.st_mode & S_IXGRP)) goto done; } else if (!(st.st_mode & S_IXOTH)) goto done; } r = 0;done: if (r) set_errno (EACCES); return r;}extern "C" intrename (const char *oldpath, const char *newpath){ sigframe thisframe (mainthread); int res = 0; char *lnk_suffix = NULL; path_conv real_old (oldpath, PC_SYM_NOFOLLOW); if (real_old.error) { syscall_printf ("-1 = rename (%s, %s)", oldpath, newpath); set_errno (real_old.error); return -1; } path_conv real_new (newpath, PC_SYM_NOFOLLOW); /* Shortcut hack. */ char new_lnk_buf[MAX_PATH + 5]; if (real_old.issymlink () && !real_new.error && !real_new.case_clash) { int len_old = strlen (real_old.get_win32 ()); if (strcasematch (real_old.get_win32 () + len_old - 4, ".lnk")) { strcpy (new_lnk_buf, newpath); strcat (new_lnk_buf, ".lnk"); newpath = new_lnk_buf; real_new.check (newpath, PC_SYM_NOFOLLOW); } } if (real_new.error || real_new.case_clash) { syscall_printf ("-1 = rename (%s, %s)", oldpath, newpath); set_errno (real_new.case_clash ? ECASECLASH : real_new.error); return -1; } if (!writable_directory (real_old) || !writable_directory (real_new)) { syscall_printf ("-1 = rename (%s, %s)", oldpath, newpath); set_errno (EACCES); return -1; } if (!real_old.exists ()) /* file to move doesn't exist */ { syscall_printf ("file to move doesn't exist"); set_errno (ENOENT); return (-1); } /* Destination file exists and is read only, change that or else the rename won't work. */ if (real_new.has_attribute (FILE_ATTRIBUTE_READONLY)) SetFileAttributes (real_new, (DWORD) real_new & ~FILE_ATTRIBUTE_READONLY); /* Shortcut hack No. 2, part 1 */ if (!real_old.issymlink () && !real_new.error && real_new.issymlink () && real_new.known_suffix && strcasematch (real_new.known_suffix, ".lnk") &&
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -