109109import com .oracle .graal .python .nodes .function .builtins .clinic .ArgumentClinicProvider ;
110110import com .oracle .graal .python .nodes .truffle .PythonArithmeticTypes ;
111111import com .oracle .graal .python .nodes .util .CastToJavaLongLossyNode ;
112- import com .oracle .graal .python .nodes .util .CastToJavaUnsignedLongNode ;
113112import com .oracle .graal .python .nodes .util .CastToTruffleStringNode ;
114113import com .oracle .graal .python .runtime .GilNode ;
115114import com .oracle .graal .python .runtime .PosixConstants ;
@@ -2212,6 +2211,134 @@ PNone chmodFollow(VirtualFrame frame, PosixFd fd, int mode, int dirFd, @Suppress
22122211 }
22132212 }
22142213
2214+ @ Builtin (name = "fchown" , parameterNames = {"fd" , "uid" , "gid" })
2215+ @ ArgumentClinic (name = "fd" , conversion = ClinicConversion .Int )
2216+ @ ArgumentClinic (name = "uid" , conversionClass = UidConversionNode .class )
2217+ @ ArgumentClinic (name = "gid" , conversionClass = GidConversionNode .class )
2218+ @ GenerateNodeFactory
2219+ abstract static class FChownNode extends PythonTernaryClinicBuiltinNode {
2220+ @ Specialization
2221+ Object chown (VirtualFrame frame , int fd , long uid , long gid ,
2222+ @ Bind ("this" ) Node inliningTarget ,
2223+ @ Cached SysModuleBuiltins .AuditNode auditNode ,
2224+ @ CachedLibrary (limit = "1" ) PosixSupportLibrary posixLib ,
2225+ @ Cached GilNode gil ,
2226+ @ Cached PConstructAndRaiseNode .Lazy constructAndRaiseNode ) {
2227+ auditNode .audit (inliningTarget , "os.chown" , fd , uid , gid , -1 );
2228+ try {
2229+ gil .release (true );
2230+ try {
2231+ posixLib .fchown (getPosixSupport (), fd , uid , gid );
2232+ } finally {
2233+ gil .acquire ();
2234+ }
2235+ } catch (PosixException e ) {
2236+ throw constructAndRaiseNode .get (inliningTarget ).raiseOSErrorFromPosixException (frame , e , fd );
2237+ }
2238+ return PNone .NONE ;
2239+ }
2240+
2241+ @ Override
2242+ protected ArgumentClinicProvider getArgumentClinic () {
2243+ return PosixModuleBuiltinsClinicProviders .FChownNodeClinicProviderGen .INSTANCE ;
2244+ }
2245+ }
2246+
2247+ @ Builtin (name = "lchown" , parameterNames = {"path" , "uid" , "gid" })
2248+ @ ArgumentClinic (name = "path" , conversionClass = PathConversionNode .class , args = {"false" , "false" })
2249+ @ ArgumentClinic (name = "uid" , conversionClass = UidConversionNode .class )
2250+ @ ArgumentClinic (name = "gid" , conversionClass = GidConversionNode .class )
2251+ @ GenerateNodeFactory
2252+ abstract static class LChownNode extends PythonTernaryClinicBuiltinNode {
2253+ @ Specialization
2254+ Object chown (VirtualFrame frame , PosixPath path , long uid , long gid ,
2255+ @ Bind ("this" ) Node inliningTarget ,
2256+ @ Cached SysModuleBuiltins .AuditNode auditNode ,
2257+ @ CachedLibrary (limit = "1" ) PosixSupportLibrary posixLib ,
2258+ @ Cached GilNode gil ,
2259+ @ Cached PConstructAndRaiseNode .Lazy constructAndRaiseNode ) {
2260+ auditNode .audit (inliningTarget , "os.chown" , path .originalObject , uid , gid , -1 );
2261+ try {
2262+ gil .release (true );
2263+ try {
2264+ posixLib .fchownat (getPosixSupport (), AT_FDCWD .value , path .value , uid , gid , false );
2265+ } finally {
2266+ gil .acquire ();
2267+ }
2268+ } catch (PosixException e ) {
2269+ throw constructAndRaiseNode .get (inliningTarget ).raiseOSErrorFromPosixException (frame , e , path .originalObject );
2270+ }
2271+ return PNone .NONE ;
2272+ }
2273+
2274+ @ Override
2275+ protected ArgumentClinicProvider getArgumentClinic () {
2276+ return PosixModuleBuiltinsClinicProviders .LChownNodeClinicProviderGen .INSTANCE ;
2277+ }
2278+ }
2279+
2280+ @ Builtin (name = "chown" , minNumOfPositionalArgs = 3 , parameterNames = {"path" , "uid" , "gid" }, keywordOnlyNames = {"dir_fd" , "follow_symlinks" })
2281+ @ ArgumentClinic (name = "path" , conversionClass = PathConversionNode .class , args = {"false" , "true" })
2282+ @ ArgumentClinic (name = "uid" , conversionClass = UidConversionNode .class )
2283+ @ ArgumentClinic (name = "gid" , conversionClass = GidConversionNode .class )
2284+ @ ArgumentClinic (name = "dir_fd" , conversionClass = DirFdConversionNode .class )
2285+ @ ArgumentClinic (name = "follow_symlinks" , conversion = ClinicConversion .Boolean , defaultValue = "true" )
2286+ @ GenerateNodeFactory
2287+ abstract static class ChownNode extends PythonClinicBuiltinNode {
2288+ @ Specialization
2289+ Object chown (VirtualFrame frame , PosixPath path , long uid , long gid , int dirFd , boolean followSymlinks ,
2290+ @ Bind ("this" ) Node inliningTarget ,
2291+ @ Shared @ Cached SysModuleBuiltins .AuditNode auditNode ,
2292+ @ Shared @ CachedLibrary (limit = "1" ) PosixSupportLibrary posixLib ,
2293+ @ Shared @ Cached GilNode gil ,
2294+ @ Shared @ Cached PConstructAndRaiseNode .Lazy constructAndRaiseNode ) {
2295+ auditNode .audit (inliningTarget , "os.chown" , path .originalObject , uid , gid , dirFd != AT_FDCWD .value ? dirFd : -1 );
2296+ try {
2297+ gil .release (true );
2298+ try {
2299+ posixLib .fchownat (getPosixSupport (), dirFd , path .value , uid , gid , followSymlinks );
2300+ } finally {
2301+ gil .acquire ();
2302+ }
2303+ } catch (PosixException e ) {
2304+ throw constructAndRaiseNode .get (inliningTarget ).raiseOSErrorFromPosixException (frame , e , path .originalObject );
2305+ }
2306+ return PNone .NONE ;
2307+ }
2308+
2309+ @ Specialization
2310+ Object chown (VirtualFrame frame , PosixFd fd , long uid , long gid , int dirFd , boolean followSymlinks ,
2311+ @ Bind ("this" ) Node inliningTarget ,
2312+ @ Shared @ Cached SysModuleBuiltins .AuditNode auditNode ,
2313+ @ Shared @ CachedLibrary (limit = "1" ) PosixSupportLibrary posixLib ,
2314+ @ Shared @ Cached GilNode gil ,
2315+ @ Shared @ Cached PConstructAndRaiseNode .Lazy constructAndRaiseNode ) {
2316+ if (dirFd != AT_FDCWD .value ) {
2317+ throw raise (ValueError , ErrorMessages .CANT_SPECIFY_BOTH_DIR_FD_AND_FD );
2318+ }
2319+ if (followSymlinks ) {
2320+ throw raise (ValueError , ErrorMessages .CANNOT_USE_FD_AND_FOLLOW_SYMLINKS_TOGETHER , "chown" );
2321+ }
2322+ auditNode .audit (inliningTarget , "os.chown" , fd .originalObject , uid , gid , -1 );
2323+ try {
2324+ gil .release (true );
2325+ try {
2326+ posixLib .fchown (getPosixSupport (), fd .fd , uid , gid );
2327+ } finally {
2328+ gil .acquire ();
2329+ }
2330+ } catch (PosixException e ) {
2331+ throw constructAndRaiseNode .get (inliningTarget ).raiseOSErrorFromPosixException (frame , e , fd .originalObject );
2332+ }
2333+ return PNone .NONE ;
2334+ }
2335+
2336+ @ Override
2337+ protected ArgumentClinicProvider getArgumentClinic () {
2338+ return PosixModuleBuiltinsClinicProviders .ChownNodeClinicProviderGen .INSTANCE ;
2339+ }
2340+ }
2341+
22152342 @ Builtin (name = "readlink" , minNumOfPositionalArgs = 1 , parameterNames = {"path" }, varArgsMarker = true , keywordOnlyNames = {"dir_fd" }, doc = "readlink(path, *, dir_fd=None) -> path\n " +
22162343 "\n Return a string representing the path to which the symbolic link points.\n " )
22172344 @ ArgumentClinic (name = "path" , conversionClass = PathConversionNode .class , args = {"false" , "false" })
@@ -3240,10 +3367,11 @@ public static PidtConversionNode create() {
32403367 }
32413368 }
32423369
3243- /**
3244- * Emulates CPython's {@code _Py_Uid_Converter()}. Always returns an {@code long}.
3245- */
3246- public abstract static class UidConversionNode extends ArgumentCastNodeWithRaise {
3370+ @ GenerateCached (false )
3371+ public abstract static class AbstractIdConversionNode extends ArgumentCastNodeWithRaise {
3372+
3373+ private static final long MAX_UINT32 = (1L << 32 ) - 1 ;
3374+
32473375 public abstract long executeLong (VirtualFrame frame , Object value );
32483376
32493377 @ Specialization
@@ -3261,39 +3389,69 @@ long doLong(long value) {
32613389 long doGeneric (VirtualFrame frame , Object value ,
32623390 @ Bind ("this" ) Node inliningTarget ,
32633391 @ Cached PyNumberIndexNode pyNumberIndexNode ,
3264- @ Cached PyLongAsLongAndOverflowNode asLongAndOverflowNode ,
3265- @ Cached CastToJavaUnsignedLongNode asUnsignedLong ) {
3392+ @ Cached PyLongAsLongNode asLongNode ) {
32663393 Object index ;
32673394 try {
32683395 index = pyNumberIndexNode .execute (frame , inliningTarget , value );
32693396 } catch (PException ex ) {
3270- throw raise (TypeError , ErrorMessages .UID_SHOULD_BE_INTEGER_NOT_P , value );
3271- }
3272- try {
3273- return checkValue (asLongAndOverflowNode .execute (frame , inliningTarget , index ));
3274- } catch (OverflowException e ) {
3275- // fall through
3397+ throw raise (TypeError , ErrorMessages .S_SHOULD_BE_INTEGER_NOT_P , getIdName (), value );
32763398 }
3277- return asUnsignedLong .execute (inliningTarget , index );
3278- // We have no means to distinguish overflow/underflow so we just let any OverflowError
3279- // from asUnsignedLong fall through. It will not have the same message as CPython, but
3280- // still correct type.
3399+ /*
3400+ * We have no means to distinguish overflow/underflow, so we just let any OverflowError
3401+ * from asLongNode fall through. It will not have the same message as CPython, but still
3402+ * correct type.
3403+ */
3404+ return checkValue (asLongNode .execute (frame , inliningTarget , index ));
32813405 }
32823406
32833407 private long checkValue (long value ) {
3408+ // Note that -1 is intentionally allowed
32843409 if (value < -1 ) {
3285- throw raise (OverflowError , ErrorMessages .UID_IS_LESS_THAN_MINIMUM );
3410+ throw raise (OverflowError , ErrorMessages .S_IS_LESS_THAN_MINIMUM , getIdName ());
3411+ } else if (value > MAX_UINT32 ) {
3412+ /* uid_t is uint32_t on Linux */
3413+ throw raise (OverflowError , ErrorMessages .S_IS_GREATER_THAN_MAXIUMUM , getIdName ());
32863414 }
32873415 return value ;
32883416 }
32893417
3418+ protected abstract String getIdName ();
3419+ }
3420+
3421+ /**
3422+ * Emulates CPython's {@code _Py_Uid_Converter()}. Always returns a {@code long}.
3423+ */
3424+ public abstract static class UidConversionNode extends AbstractIdConversionNode {
3425+
3426+ @ Override
3427+ protected String getIdName () {
3428+ return "uid" ;
3429+ }
3430+
32903431 @ ClinicConverterFactory (shortCircuitPrimitive = {PrimitiveType .Int , PrimitiveType .Long })
32913432 @ NeverDefault
32923433 public static UidConversionNode create () {
32933434 return PosixModuleBuiltinsFactory .UidConversionNodeGen .create ();
32943435 }
32953436 }
32963437
3438+ /**
3439+ * Emulates CPython's {@code _Py_Gid_Converter()}. Always returns a {@code long}.
3440+ */
3441+ public abstract static class GidConversionNode extends AbstractIdConversionNode {
3442+
3443+ @ Override
3444+ protected String getIdName () {
3445+ return "gid" ;
3446+ }
3447+
3448+ @ ClinicConverterFactory (shortCircuitPrimitive = {PrimitiveType .Int , PrimitiveType .Long })
3449+ @ NeverDefault
3450+ public static GidConversionNode create () {
3451+ return PosixModuleBuiltinsFactory .GidConversionNodeGen .create ();
3452+ }
3453+ }
3454+
32973455 /**
32983456 * Represents the result of {@code path_t} conversion. Similar to CPython's {@code path_t}
32993457 * structure, but only contains the results of the conversion, not the conversion parameters.
0 commit comments