Skip to content

Commit 69302c9

Browse files
committed
Implement os.link
1 parent 966b51c commit 69302c9

File tree

12 files changed

+96
-8
lines changed

12 files changed

+96
-8
lines changed

graalpython/com.oracle.graal.python.cext/posix/posix.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -347,6 +347,10 @@ int32_t call_unlinkat(int32_t dirFd, const char *pathname, int32_t rmdir) {
347347
return unlinkat(dirFd, pathname, rmdir ? AT_REMOVEDIR : 0);
348348
}
349349

350+
int32_t call_linkat(int32_t oldDirFd, const char *oldPath, int32_t newDirFd, const char *newPath, int32_t flags) {
351+
return linkat(oldDirFd, oldPath, newDirFd, newPath, flags);
352+
}
353+
350354
int32_t call_symlinkat(const char *target, int32_t dirFd, const char *linkpath) {
351355
return symlinkat(target, dirFd, linkpath);
352356
}

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/builtins/modules/PosixModuleBuiltins.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@
2929
import static com.oracle.graal.python.nodes.BuiltinNames.T_POSIX;
3030
import static com.oracle.graal.python.nodes.StringLiterals.T_DOT;
3131
import static com.oracle.graal.python.runtime.PosixConstants.AT_FDCWD;
32+
import static com.oracle.graal.python.runtime.PosixConstants.AT_SYMLINK_FOLLOW;
3233
import static com.oracle.graal.python.runtime.PosixConstants.O_CLOEXEC;
3334
import static com.oracle.graal.python.runtime.exception.PythonErrorType.NotImplementedError;
3435
import static com.oracle.graal.python.runtime.exception.PythonErrorType.OverflowError;
@@ -1261,6 +1262,32 @@ protected ArgumentClinicProvider getArgumentClinic() {
12611262
}
12621263
}
12631264

1265+
@Builtin(name = "link", minNumOfPositionalArgs = 2, parameterNames = {"src", "dst"}, keywordOnlyNames = {"src_dir_fd", "dst_dir_fd", "follow_symlinks"})
1266+
@ArgumentClinic(name = "src", conversionClass = PathConversionNode.class, args = {"false", "false"})
1267+
@ArgumentClinic(name = "dst", conversionClass = PathConversionNode.class, args = {"false", "false"})
1268+
@ArgumentClinic(name = "src_dir_fd", conversionClass = DirFdConversionNode.class)
1269+
@ArgumentClinic(name = "dst_dir_fd", conversionClass = DirFdConversionNode.class)
1270+
@ArgumentClinic(name = "follow_symlinks", conversion = ClinicConversion.Boolean, defaultValue = "false")
1271+
@GenerateNodeFactory
1272+
abstract static class LinkNode extends PythonClinicBuiltinNode {
1273+
1274+
@Override
1275+
protected ArgumentClinicProvider getArgumentClinic() {
1276+
return PosixModuleBuiltinsClinicProviders.LinkNodeClinicProviderGen.INSTANCE;
1277+
}
1278+
1279+
@Specialization
1280+
PNone link(VirtualFrame frame, PosixPath src, PosixPath dst, int srcDirFd, int dstDirFd, boolean followSymlinks,
1281+
@CachedLibrary("getPosixSupport()") PosixSupportLibrary posixLib) {
1282+
try {
1283+
posixLib.linkat(getPosixSupport(), srcDirFd, src.value, dstDirFd, dst.value, followSymlinks ? AT_SYMLINK_FOLLOW.value : 0);
1284+
} catch (PosixException e) {
1285+
throw raiseOSErrorFromPosixException(frame, e, src.originalObject, dst.originalObject);
1286+
}
1287+
return PNone.NONE;
1288+
}
1289+
}
1290+
12641291
@Builtin(name = "symlink", minNumOfPositionalArgs = 2, parameterNames = {"src", "dst", "target_is_directory"}, keywordOnlyNames = {"dir_fd"})
12651292
@ArgumentClinic(name = "src", conversionClass = PathConversionNode.class, args = {"false", "false"})
12661293
@ArgumentClinic(name = "dst", conversionClass = PathConversionNode.class, args = {"false", "false"})

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/EmulatedPosixSupport.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1250,6 +1250,28 @@ public void unlinkat(int dirFd, Object path, @SuppressWarnings("unused") boolean
12501250
}
12511251
}
12521252

1253+
@ExportMessage
1254+
public void linkat(int oldFdDir, Object oldPath, int newFdDir, Object newPath, int flags,
1255+
@Shared("errorBranch") @Cached BranchProfile errorBranch,
1256+
@Shared("defaultDirProfile") @Cached ConditionProfile defaultDirFdPofile,
1257+
@Shared("eq") @Cached TruffleString.EqualNode eqNode,
1258+
@Shared("js2ts") @Cached TruffleString.FromJavaStringNode fromJavaStringNode,
1259+
@Shared("ts2js") @Cached TruffleString.ToJavaStringNode toJavaStringNode) throws PosixException {
1260+
TruffleString srcPath = pathToTruffleString(oldPath, fromJavaStringNode);
1261+
TruffleFile srcFile = resolvePath(oldFdDir, srcPath, defaultDirFdPofile, eqNode, toJavaStringNode);
1262+
TruffleString dstPath = pathToTruffleString(newPath, fromJavaStringNode);
1263+
TruffleFile dstFile = resolvePath(newFdDir, srcPath, defaultDirFdPofile, eqNode, toJavaStringNode);
1264+
try {
1265+
if ((flags & PosixConstants.AT_SYMLINK_FOLLOW.value) != 0) {
1266+
dstFile = dstFile.getCanonicalFile();
1267+
}
1268+
srcFile.createLink(dstFile);
1269+
} catch (Exception e) {
1270+
errorBranch.enter();
1271+
throw posixException(OSErrorEnum.fromException(e, eqNode));
1272+
}
1273+
}
1274+
12531275
@ExportMessage
12541276
public void symlinkat(Object target, int linkDirFd, Object link,
12551277
@Shared("errorBranch") @Cached BranchProfile errorBranch,

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/ImageBuildtimePosixSupport.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -348,6 +348,13 @@ final void unlinkat(int dirFd, Object pathname, boolean rmdir,
348348
nativeLib.unlinkat(nativePosixSupport, dirFd, pathname, rmdir);
349349
}
350350

351+
@ExportMessage
352+
final void linkat(int oldFdDir, Object oldPath, int newFdDir, Object newPath, int flags,
353+
@CachedLibrary("this.nativePosixSupport") PosixSupportLibrary nativeLib) throws PosixException {
354+
checkNotInImageBuildtime();
355+
nativeLib.linkat(nativePosixSupport, oldFdDir, oldPath, newFdDir, newPath, flags);
356+
}
357+
351358
@ExportMessage
352359
final void symlinkat(Object target, int linkpathDirFd, Object linkpath,
353360
@CachedLibrary("this.nativePosixSupport") PosixSupportLibrary nativeLib) throws PosixException {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/LoggingPosixSupport.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -400,6 +400,17 @@ final void unlinkat(int dirFd, Object pathname, boolean rmdir,
400400
}
401401
}
402402

403+
@ExportMessage
404+
final void linkat(int oldFdDir, Object oldPath, int newFdDir, Object newPath, int flags,
405+
@CachedLibrary("this.delegate") PosixSupportLibrary lib) throws PosixException {
406+
logEnter("linkAt", "%d, %s, %d, %s, %d", oldFdDir, oldPath, newFdDir, newPath, flags);
407+
try {
408+
lib.linkat(delegate, oldFdDir, oldPath, newFdDir, newPath, flags);
409+
} catch (PosixException e) {
410+
throw logException("symlinkAt", e);
411+
}
412+
}
413+
403414
@ExportMessage
404415
final void symlinkat(Object target, int linkpathDirFd, Object linkpath,
405416
@CachedLibrary("this.delegate") PosixSupportLibrary lib) throws PosixException {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/NFIPosixSupport.java

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,6 @@
4141
// skip GIL
4242
package com.oracle.graal.python.runtime;
4343

44-
import com.oracle.truffle.api.dsl.NeverDefault;
45-
4644
import static com.oracle.graal.python.nodes.StringLiterals.T_LLVM_LANGUAGE;
4745
import static com.oracle.graal.python.nodes.StringLiterals.T_NATIVE;
4846
import static com.oracle.graal.python.runtime.PosixConstants.AF_INET;
@@ -104,6 +102,7 @@
104102
import com.oracle.truffle.api.TruffleSafepoint;
105103
import com.oracle.truffle.api.dsl.Cached;
106104
import com.oracle.truffle.api.dsl.Cached.Shared;
105+
import com.oracle.truffle.api.dsl.NeverDefault;
107106
import com.oracle.truffle.api.dsl.Specialization;
108107
import com.oracle.truffle.api.interop.ArityException;
109108
import com.oracle.truffle.api.interop.InteropLibrary;
@@ -167,6 +166,7 @@ private enum PosixNativeFunction {
167166
call_fstatvfs("(sint32, [sint64]):sint32"),
168167
call_uname("([sint8], [sint8], [sint8], [sint8], [sint8], sint32):sint32"),
169168
call_unlinkat("(sint32, [sint8], sint32):sint32"),
169+
call_linkat("(sint32, [sint8], sint32, [sint8], sint32):sint32"),
170170
call_symlinkat("([sint8], sint32, [sint8]):sint32"),
171171
call_mkdirat("(sint32, [sint8], sint32):sint32"),
172172
call_getcwd("([sint8], uint64):sint32"),
@@ -729,6 +729,15 @@ public void unlinkat(int dirFd, Object pathname, boolean rmdir,
729729
}
730730
}
731731

732+
@ExportMessage
733+
public void linkat(int oldFdDir, Object oldPath, int newFdDir, Object newPath, int flags,
734+
@Shared("invoke") @Cached InvokeNativeFunction invokeNode) throws PosixException {
735+
int result = invokeNode.callInt(this, PosixNativeFunction.call_linkat, oldFdDir, pathToCString(oldPath), newFdDir, pathToCString(newPath), flags);
736+
if (result != 0) {
737+
throw newPosixException(invokeNode, getErrno(invokeNode));
738+
}
739+
}
740+
732741
@ExportMessage
733742
public void symlinkat(Object target, int linkpathDirFd, Object linkpath,
734743
@Shared("invoke") @Cached InvokeNativeFunction invokeNode) throws PosixException {

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstants.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,7 @@ public final class PosixConstants {
8989
public static final MandatoryIntConstant NI_MAXHOST;
9090
public static final MandatoryIntConstant NI_MAXSERV;
9191
public static final MandatoryIntConstant AT_FDCWD;
92+
public static final MandatoryIntConstant AT_SYMLINK_FOLLOW;
9293
public static final MandatoryIntConstant SEEK_SET;
9394
public static final MandatoryIntConstant SEEK_CUR;
9495
public static final MandatoryIntConstant SEEK_END;
@@ -341,6 +342,7 @@ public final class PosixConstants {
341342
NI_MAXHOST = reg.createMandatoryInt("NI_MAXHOST");
342343
NI_MAXSERV = reg.createMandatoryInt("NI_MAXSERV");
343344
AT_FDCWD = reg.createMandatoryInt("AT_FDCWD");
345+
AT_SYMLINK_FOLLOW = reg.createMandatoryInt("AT_SYMLINK_FOLLOW");
344346
SEEK_SET = reg.createMandatoryInt("SEEK_SET");
345347
SEEK_CUR = reg.createMandatoryInt("SEEK_CUR");
346348
SEEK_END = reg.createMandatoryInt("SEEK_END");

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsDarwin.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
*/
4141
package com.oracle.graal.python.runtime;
4242

43-
// Auto generated by gen_native_cfg.py at 2023-01-05 19:09:30.402303
44-
// on Darwin ol-mac-mini2-prague.cz.oracle.com 21.6.0 Darwin Kernel Version 21.6.0: Sun Nov 6 23:31:16 PST 2022; root:xnu-8020.240.14~1/RELEASE_X86_64 x86_64 i386
43+
// Auto generated by gen_native_cfg.py at 2023-02-16 18:27:17.595009
44+
// on Darwin ol-mac-mini2-prague.cz.oracle.com 21.6.0 Darwin Kernel Version 21.6.0: Mon Dec 19 20:44:01 PST 2022; root:xnu-8020.240.18~2/RELEASE_X86_64 x86_64 i386
4545
class PosixConstantsDarwin {
4646

4747
private PosixConstantsDarwin() {
@@ -60,6 +60,7 @@ static void getConstants(PosixConstants.Registry constants) {
6060
constants.put("NI_MAXHOST", 1025);
6161
constants.put("NI_MAXSERV", 32);
6262
constants.put("AT_FDCWD", -2);
63+
constants.put("AT_SYMLINK_FOLLOW", 64);
6364
constants.put("SEEK_SET", 0);
6465
constants.put("SEEK_CUR", 1);
6566
constants.put("SEEK_END", 2);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsLinux.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,8 @@
4040
*/
4141
package com.oracle.graal.python.runtime;
4242

43-
// Auto generated by gen_native_cfg.py at 2023-01-05 18:51:07.224339
44-
// on Linux arisu 6.0.15-300.fc37.x86_64 #1 SMP PREEMPT_DYNAMIC Wed Dec 21 18:33:23 UTC 2022 x86_64 x86_64
43+
// Auto generated by gen_native_cfg.py at 2023-02-15 17:36:59.628778
44+
// on Linux arisu 6.1.10-200.fc37.x86_64 #1 SMP PREEMPT_DYNAMIC Mon Feb 6 23:56:48 UTC 2023 x86_64 x86_64
4545
class PosixConstantsLinux {
4646

4747
private PosixConstantsLinux() {
@@ -61,6 +61,7 @@ static void getConstants(PosixConstants.Registry constants) {
6161
constants.put("NI_MAXHOST", 1025);
6262
constants.put("NI_MAXSERV", 32);
6363
constants.put("AT_FDCWD", -100);
64+
constants.put("AT_SYMLINK_FOLLOW", 1024);
6465
constants.put("SEEK_SET", 0);
6566
constants.put("SEEK_CUR", 1);
6667
constants.put("SEEK_END", 2);

graalpython/com.oracle.graal.python/src/com/oracle/graal/python/runtime/PosixConstantsWin32.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright (c) 2021, 2022, Oracle and/or its affiliates. All rights reserved.
2+
* Copyright (c) 2021, 2023, Oracle and/or its affiliates. All rights reserved.
33
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
44
*
55
* The Universal Permissive License (UPL), Version 1.0
@@ -60,6 +60,7 @@ static void getConstants(PosixConstants.Registry constants) {
6060
constants.put("NI_MAXHOST", 1025);
6161
constants.put("NI_MAXSERV", 32);
6262
constants.put("AT_FDCWD", 0);
63+
constants.put("AT_SYMLINK_FOLLOW", 0);
6364
constants.put("SEEK_SET", 0);
6465
constants.put("SEEK_CUR", 1);
6566
constants.put("SEEK_END", 2);

0 commit comments

Comments
 (0)