@@ -160,6 +160,8 @@ static njs_int_t njs_fs_read_file(njs_vm_t *vm, njs_value_t *args,
160160 njs_uint_t nargs , njs_index_t calltype , njs_value_t * retval );
161161static njs_int_t njs_fs_readdir (njs_vm_t * vm , njs_value_t * args ,
162162 njs_uint_t nargs , njs_index_t calltype , njs_value_t * retval );
163+ static njs_int_t njs_fs_readlink (njs_vm_t * vm , njs_value_t * args ,
164+ njs_uint_t nargs , njs_index_t calltype , njs_value_t * retval );
163165static njs_int_t njs_fs_realpath (njs_vm_t * vm , njs_value_t * args ,
164166 njs_uint_t nargs , njs_index_t calltype , njs_value_t * retval );
165167static njs_int_t njs_fs_rename (njs_vm_t * vm , njs_value_t * args ,
@@ -415,6 +417,17 @@ static njs_external_t njs_ext_fs_promises[] = {
415417 }
416418 },
417419
420+ {
421+ .flags = NJS_EXTERN_METHOD ,
422+ .name .string = njs_str ("readlink" ),
423+ .writable = 1 ,
424+ .configurable = 1 ,
425+ .u .method = {
426+ .native = njs_fs_readlink ,
427+ .magic8 = NJS_FS_PROMISE ,
428+ }
429+ },
430+
418431 {
419432 .flags = NJS_EXTERN_METHOD ,
420433 .name .string = njs_str ("realpath" ),
@@ -726,6 +739,28 @@ static njs_external_t njs_ext_fs[] = {
726739 }
727740 },
728741
742+ {
743+ .flags = NJS_EXTERN_METHOD ,
744+ .name .string = njs_str ("readlink" ),
745+ .writable = 1 ,
746+ .configurable = 1 ,
747+ .u .method = {
748+ .native = njs_fs_readlink ,
749+ .magic8 = NJS_FS_CALLBACK ,
750+ }
751+ },
752+
753+ {
754+ .flags = NJS_EXTERN_METHOD ,
755+ .name .string = njs_str ("readlinkSync" ),
756+ .writable = 1 ,
757+ .configurable = 1 ,
758+ .u .method = {
759+ .native = njs_fs_readlink ,
760+ .magic8 = NJS_FS_DIRECT ,
761+ }
762+ },
763+
729764 {
730765 .flags = NJS_EXTERN_METHOD ,
731766 .name .string = njs_str ("realpath" ),
@@ -2035,6 +2070,99 @@ njs_fs_readdir(njs_vm_t *vm, njs_value_t *args, njs_uint_t nargs,
20352070}
20362071
20372072
2073+ static njs_int_t
2074+ njs_fs_readlink (njs_vm_t * vm , njs_value_t * args , njs_uint_t nargs ,
2075+ njs_index_t calltype , njs_value_t * retval )
2076+ {
2077+ ssize_t n ;
2078+ njs_int_t ret ;
2079+ njs_str_t s ;
2080+ const char * path ;
2081+ njs_value_t * callback , * options ;
2082+ njs_opaque_value_t encode , result ;
2083+ const njs_buffer_encoding_t * encoding ;
2084+ char path_buf [NJS_MAX_PATH + 1 ],
2085+ dst_buf [NJS_MAX_PATH + 1 ];
2086+
2087+ path = njs_fs_path (vm , path_buf , njs_arg (args , nargs , 1 ), "path" );
2088+ if (njs_slow_path (path == NULL )) {
2089+ return NJS_ERROR ;
2090+ }
2091+
2092+ callback = NULL ;
2093+ options = njs_arg (args , nargs , 2 );
2094+
2095+ if (calltype == NJS_FS_CALLBACK ) {
2096+ callback = njs_arg (args , nargs , njs_min (nargs - 1 , 3 ));
2097+ if (!njs_value_is_function (callback )) {
2098+ njs_vm_type_error (vm , "\"callback\" must be a function" );
2099+ return NJS_ERROR ;
2100+ }
2101+
2102+ if (options == callback ) {
2103+ options = njs_value_arg (& njs_value_undefined );
2104+ }
2105+ }
2106+
2107+ njs_value_undefined_set (njs_value_arg (& encode ));
2108+
2109+ if (njs_value_is_string (options )) {
2110+ njs_value_assign (& encode , options );
2111+
2112+ } else if (!njs_value_is_undefined (options )) {
2113+ if (!njs_value_is_object (options )) {
2114+ njs_vm_type_error (vm , "Unknown options type "
2115+ "(a string or object required)" );
2116+ return NJS_ERROR ;
2117+ }
2118+
2119+ (void ) njs_vm_object_prop (vm , options , & string_encoding , & encode );
2120+ }
2121+
2122+ encoding = NULL ;
2123+
2124+ if (njs_value_is_string (njs_value_arg (& encode ))) {
2125+ njs_value_string_get (njs_value_arg (& encode ), & s );
2126+
2127+ } else {
2128+ s .length = 0 ;
2129+ s .start = NULL ;
2130+ }
2131+
2132+ if (!njs_strstr_eq (& s , & string_buffer )) {
2133+ encoding = njs_buffer_encoding (vm , njs_value_arg (& encode ), 1 );
2134+ if (njs_slow_path (encoding == NULL )) {
2135+ return NJS_ERROR ;
2136+ }
2137+ }
2138+
2139+ s .start = (u_char * ) dst_buf ;
2140+ n = readlink (path , dst_buf , sizeof (dst_buf ) - 1 );
2141+ if (njs_slow_path (n < 0 )) {
2142+ ret = njs_fs_error (vm , "readlink" , strerror (errno ), path , errno ,
2143+ & result );
2144+ goto done ;
2145+ }
2146+
2147+ s .length = n ;
2148+
2149+ if (encoding == NULL ) {
2150+ ret = njs_buffer_new (vm , njs_value_arg (& result ), s .start , s .length );
2151+
2152+ } else {
2153+ ret = encoding -> encode (vm , njs_value_arg (& result ), & s );
2154+ }
2155+
2156+ done :
2157+
2158+ if (ret == NJS_OK ) {
2159+ return njs_fs_result (vm , & result , calltype , callback , 2 , retval );
2160+ }
2161+
2162+ return NJS_ERROR ;
2163+ }
2164+
2165+
20382166static njs_int_t
20392167njs_fs_realpath (njs_vm_t * vm , njs_value_t * args , njs_uint_t nargs ,
20402168 njs_index_t calltype , njs_value_t * retval )
0 commit comments