1 /*
  2  * Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.
  3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
  4  *
  5  * This code is free software; you can redistribute it and/or modify it
  6  * under the terms of the GNU General Public License version 2 only, as
  7  * published by the Free Software Foundation.  Oracle designates this
  8  * particular file as subject to the "Classpath" exception as provided
  9  * by Oracle in the LICENSE file that accompanied this code.
 10  *
 11  * This code is distributed in the hope that it will be useful, but WITHOUT
 12  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 13  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 14  * version 2 for more details (a copy is included in the LICENSE file that
 15  * accompanied this code).
 16  *
 17  * You should have received a copy of the GNU General Public License version
 18  * 2 along with this work; if not, write to the Free Software Foundation,
 19  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 20  *
 21  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 22  * or visit www.oracle.com if you need additional information or have any
 23  * questions.
 24  */
 25 
 26 package sun.nio.fs;
 27 
 28 /**
 29  * Unix system and library calls.
 30  */
 31 
 32 class UnixNativeDispatcher {
 33     protected UnixNativeDispatcher() { }
 34 
 35     // returns a NativeBuffer containing the given path
 36     static NativeBuffer copyToNativeBuffer(UnixPath path) {
 37         byte[] cstr = path.getByteArrayForSysCalls();
 38         int size = cstr.length + 1;
 39         NativeBuffer buffer = NativeBuffers.getNativeBufferFromCache(size);
 40         if (buffer == null) {
 41             buffer = NativeBuffers.allocNativeBuffer(size);
 42         } else {
 43             // buffer already contains the path
 44             if (buffer.owner() == path)
 45                 return buffer;
 46         }
 47         NativeBuffers.copyCStringToNativeBuffer(cstr, buffer);
 48         buffer.setOwner(path);
 49         return buffer;
 50     }
 51 
 52     /**
 53      * char *getcwd(char *buf, size_t size);
 54      */
 55     static native byte[] getcwd();
 56 
 57     /**
 58      * int dup(int filedes)
 59      */
 60     static native int dup(int filedes) throws UnixException;
 61 
 62     /**
 63      * int open(const char* path, int oflag, mode_t mode)
 64      */
 65     static int open(UnixPath path, int flags, int mode) throws UnixException {
 66         NativeBuffer buffer = copyToNativeBuffer(path);
 67         try {
 68             return open0(buffer.address(), flags, mode);
 69         } finally {
 70             buffer.release();
 71         }
 72     }
 73     private static native int open0(long pathAddress, int flags, int mode)
 74         throws UnixException;
 75 
 76     /**
 77      * int openat(int dfd, const char* path, int oflag, mode_t mode)
 78      */
 79     static int openat(int dfd, byte[] path, int flags, int mode) throws UnixException {
 80         NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
 81         try {
 82             return openat0(dfd, buffer.address(), flags, mode);
 83         } finally {
 84             buffer.release();
 85         }
 86     }
 87     private static native int openat0(int dfd, long pathAddress, int flags, int mode)
 88         throws UnixException;
 89 
 90     /**
 91      * close(int filedes). If fd is -1 this is a no-op.
 92      */
 93     static void close(int fd) {
 94         if (fd != -1) {
 95             close0(fd);
 96         }
 97     }
 98     private static native void close0(int fd);
 99 
100     /**
101      * void rewind(FILE* stream);
102      */
103     static native void rewind(long stream) throws UnixException;
104 
105     /**
106      * ssize_t getline(char **lineptr, size_t *n, FILE *stream);
107      */
108     static native int getlinelen(long stream) throws UnixException;
109 
110     /**
111      * link(const char* existing, const char* new)
112      */
113     static void link(UnixPath existing, UnixPath newfile) throws UnixException {
114         NativeBuffer existingBuffer = copyToNativeBuffer(existing);
115         NativeBuffer newBuffer = copyToNativeBuffer(newfile);
116         try {
117             link0(existingBuffer.address(), newBuffer.address());
118         } finally {
119             newBuffer.release();
120             existingBuffer.release();
121         }
122     }
123     private static native void link0(long existingAddress, long newAddress)
124         throws UnixException;
125 
126     /**
127      * unlink(const char* path)
128      */
129     static void unlink(UnixPath path) throws UnixException {
130         NativeBuffer buffer = copyToNativeBuffer(path);
131         try {
132             unlink0(buffer.address());
133         } finally {
134             buffer.release();
135         }
136     }
137     private static native void unlink0(long pathAddress) throws UnixException;
138 
139     /**
140      * unlinkat(int dfd, const char* path, int flag)
141      */
142     static void unlinkat(int dfd, byte[] path, int flag) throws UnixException {
143         NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
144         try {
145             unlinkat0(dfd, buffer.address(), flag);
146         } finally {
147             buffer.release();
148         }
149     }
150     private static native void unlinkat0(int dfd, long pathAddress, int flag)
151         throws UnixException;
152 
153     /**
154      * mknod(const char* path, mode_t mode, dev_t dev)
155      */
156     static void mknod(UnixPath path, int mode, long dev) throws UnixException {
157         NativeBuffer buffer = copyToNativeBuffer(path);
158         try {
159             mknod0(buffer.address(), mode, dev);
160         } finally {
161             buffer.release();
162         }
163     }
164     private static native void mknod0(long pathAddress, int mode, long dev)
165         throws UnixException;
166 
167     /**
168      *  rename(const char* old, const char* new)
169      */
170     static void rename(UnixPath from, UnixPath to) throws UnixException {
171         NativeBuffer fromBuffer = copyToNativeBuffer(from);
172         NativeBuffer toBuffer = copyToNativeBuffer(to);
173         try {
174             rename0(fromBuffer.address(), toBuffer.address());
175         } finally {
176             toBuffer.release();
177             fromBuffer.release();
178         }
179     }
180     private static native void rename0(long fromAddress, long toAddress)
181         throws UnixException;
182 
183     /**
184      *  renameat(int fromfd, const char* old, int tofd, const char* new)
185      */
186     static void renameat(int fromfd, byte[] from, int tofd, byte[] to) throws UnixException {
187         NativeBuffer fromBuffer = NativeBuffers.asNativeBuffer(from);
188         NativeBuffer toBuffer = NativeBuffers.asNativeBuffer(to);
189         try {
190             renameat0(fromfd, fromBuffer.address(), tofd, toBuffer.address());
191         } finally {
192             toBuffer.release();
193             fromBuffer.release();
194         }
195     }
196     private static native void renameat0(int fromfd, long fromAddress, int tofd, long toAddress)
197         throws UnixException;
198 
199     /**
200      * mkdir(const char* path, mode_t mode)
201      */
202     static void mkdir(UnixPath path, int mode) throws UnixException {
203         NativeBuffer buffer = copyToNativeBuffer(path);
204         try {
205             mkdir0(buffer.address(), mode);
206         } finally {
207             buffer.release();
208         }
209     }
210     private static native void mkdir0(long pathAddress, int mode) throws UnixException;
211 
212     /**
213      * rmdir(const char* path)
214      */
215     static void rmdir(UnixPath path) throws UnixException {
216         NativeBuffer buffer = copyToNativeBuffer(path);
217         try {
218             rmdir0(buffer.address());
219         } finally {
220             buffer.release();
221         }
222     }
223     private static native void rmdir0(long pathAddress) throws UnixException;
224 
225     /**
226      * readlink(const char* path, char* buf, size_t bufsize)
227      *
228      * @return  link target
229      */
230     static byte[] readlink(UnixPath path) throws UnixException {
231         NativeBuffer buffer = copyToNativeBuffer(path);
232         try {
233             return readlink0(buffer.address());
234         } finally {
235             buffer.release();
236         }
237     }
238     private static native byte[] readlink0(long pathAddress) throws UnixException;
239 
240     /**
241      * realpath(const char* path, char* resolved_name)
242      *
243      * @return  resolved path
244      */
245     static byte[] realpath(UnixPath path) throws UnixException {
246         NativeBuffer buffer = copyToNativeBuffer(path);
247         try {
248             return realpath0(buffer.address());
249         } finally {
250             buffer.release();
251         }
252     }
253     private static native byte[] realpath0(long pathAddress) throws UnixException;
254 
255     /**
256      * symlink(const char* name1, const char* name2)
257      */
258     static void symlink(byte[] name1, UnixPath name2) throws UnixException {
259         NativeBuffer targetBuffer = NativeBuffers.asNativeBuffer(name1);
260         NativeBuffer linkBuffer = copyToNativeBuffer(name2);
261         try {
262             symlink0(targetBuffer.address(), linkBuffer.address());
263         } finally {
264             linkBuffer.release();
265             targetBuffer.release();
266         }
267     }
268     private static native void symlink0(long name1, long name2)
269         throws UnixException;
270 
271     /**
272      * stat(const char* path, struct stat* buf)
273      */
274     static void stat(UnixPath path, UnixFileAttributes attrs) throws UnixException {
275         NativeBuffer buffer = copyToNativeBuffer(path);
276         try {
277             stat0(buffer.address(), attrs);
278         } finally {
279             buffer.release();
280         }
281     }
282     private static native void stat0(long pathAddress, UnixFileAttributes attrs)
283         throws UnixException;
284 
285 
286     /**
287      * stat(const char* path, struct stat* buf)
288      *
289      * @return st_mode (file type and mode) or 0 if an error occurs.
290      */
291     static int stat(UnixPath path) {
292         NativeBuffer buffer = copyToNativeBuffer(path);
293         try {
294             return stat1(buffer.address());
295         } finally {
296             buffer.release();
297         }
298     }
299     private static native int stat1(long pathAddress);
300 
301 
302     /**
303      * lstat(const char* path, struct stat* buf)
304      */
305     static void lstat(UnixPath path, UnixFileAttributes attrs) throws UnixException {
306         NativeBuffer buffer = copyToNativeBuffer(path);
307         try {
308             lstat0(buffer.address(), attrs);
309         } finally {
310             buffer.release();
311         }
312     }
313     private static native void lstat0(long pathAddress, UnixFileAttributes attrs)
314         throws UnixException;
315 
316     /**
317      * fstat(int filedes, struct stat* buf)
318      */
319     static native void fstat(int fd, UnixFileAttributes attrs) throws UnixException;
320 
321     /**
322      * fstatat(int filedes,const char* path,  struct stat* buf, int flag)
323      */
324     static void fstatat(int dfd, byte[] path, int flag, UnixFileAttributes attrs)
325         throws UnixException
326     {
327         NativeBuffer buffer = NativeBuffers.asNativeBuffer(path);
328         try {
329             fstatat0(dfd, buffer.address(), flag, attrs);
330         } finally {
331             buffer.release();
332         }
333     }
334     private static native void fstatat0(int dfd, long pathAddress, int flag,
335         UnixFileAttributes attrs) throws UnixException;
336 
337     /**
338      * chown(const char* path, uid_t owner, gid_t group)
339      */
340     static void chown(UnixPath path, int uid, int gid) throws UnixException {
341         NativeBuffer buffer = copyToNativeBuffer(path);
342         try {
343             chown0(buffer.address(), uid, gid);
344         } finally {
345             buffer.release();
346         }
347     }
348     private static native void chown0(long pathAddress, int uid, int gid)
349         throws UnixException;
350 
351     /**
352      * lchown(const char* path, uid_t owner, gid_t group)
353      */
354     static void lchown(UnixPath path, int uid, int gid) throws UnixException {
355         NativeBuffer buffer = copyToNativeBuffer(path);
356         try {
357             lchown0(buffer.address(), uid, gid);
358         } finally {
359             buffer.release();
360         }
361     }
362     private static native void lchown0(long pathAddress, int uid, int gid)
363         throws UnixException;
364 
365     /**
366      * fchown(int filedes, uid_t owner, gid_t group)
367      */
368     static native void fchown(int fd, int uid, int gid) throws UnixException;
369 
370     /**
371      * chmod(const char* path, mode_t mode)
372      */
373     static void chmod(UnixPath path, int mode) throws UnixException {
374         NativeBuffer buffer = copyToNativeBuffer(path);
375         try {
376             chmod0(buffer.address(), mode);
377         } finally {
378             buffer.release();
379         }
380     }
381     private static native void chmod0(long pathAddress, int mode)
382         throws UnixException;
383 
384     /**
385      * fchmod(int fildes, mode_t mode)
386      */
387     static native void fchmod(int fd, int mode) throws UnixException;
388 
389     /**
390      * utimes(const char* path, const struct timeval times[2])
391      */
392     static void utimes(UnixPath path, long times0, long times1)
393         throws UnixException
394     {
395         NativeBuffer buffer = copyToNativeBuffer(path);
396         try {
397             utimes0(buffer.address(), times0, times1);
398         } finally {
399             buffer.release();
400         }
401     }
402     private static native void utimes0(long pathAddress, long times0, long times1)
403         throws UnixException;
404 
405     /**
406      * futimes(int fildes, const struct timeval times[2])
407      */
408     static native void futimes(int fd, long times0, long times1) throws UnixException;
409 
410     /**
411      * futimens(int fildes, const struct timespec times[2])
412      */
413     static native void futimens(int fd, long times0, long times1) throws UnixException;
414 
415     /**
416      * lutimes(const char* path, const struct timeval times[2])
417      */
418     static void lutimes(UnixPath path, long times0, long times1)
419         throws UnixException
420     {
421         NativeBuffer buffer = copyToNativeBuffer(path);
422         try {
423             lutimes0(buffer.address(), times0, times1);
424         } finally {
425             buffer.release();
426         }
427     }
428     private static native void lutimes0(long pathAddress, long times0, long times1)
429         throws UnixException;
430 
431     /**
432      * DIR *opendir(const char* dirname)
433      */
434     static long opendir(UnixPath path) throws UnixException {
435         NativeBuffer buffer = copyToNativeBuffer(path);
436         try {
437             return opendir0(buffer.address());
438         } finally {
439             buffer.release();
440         }
441     }
442     private static native long opendir0(long pathAddress) throws UnixException;
443 
444     /**
445      * DIR* fdopendir(int filedes)
446      */
447     static native long fdopendir(int dfd) throws UnixException;
448 
449 
450     /**
451      * closedir(DIR* dirp)
452      */
453     static native void closedir(long dir) throws UnixException;
454 
455     /**
456      * struct dirent* readdir(DIR *dirp)
457      *
458      * @return  dirent->d_name
459      */
460     static native byte[] readdir(long dir) throws UnixException;
461 
462     /**
463      * size_t read(int fildes, void* buf, size_t nbyte)
464      */
465     static native int read(int fildes, long buf, int nbyte) throws UnixException;
466 
467     /**
468      * size_t writeint fildes, void* buf, size_t nbyte)
469      */
470     static native int write(int fildes, long buf, int nbyte) throws UnixException;
471 
472     /**
473      * access(const char* path, int amode);
474      */
475     static void access(UnixPath path, int amode) throws UnixException {
476         NativeBuffer buffer = copyToNativeBuffer(path);
477         try {
478             access0(buffer.address(), amode);
479         } finally {
480             buffer.release();
481         }
482     }
483     private static native void access0(long pathAddress, int amode) throws UnixException;
484 
485     /**
486      * access(constant char* path, F_OK)
487      *
488      * @return true if the file exists, false otherwise
489      */
490     static boolean exists(UnixPath path) {
491         NativeBuffer buffer = copyToNativeBuffer(path);
492         try {
493             return exists0(buffer.address());
494         } finally {
495             buffer.release();
496         }
497     }
498     private static native boolean exists0(long pathAddress);
499 
500 
501     /**
502      * struct passwd *getpwuid(uid_t uid);
503      *
504      * @return  passwd->pw_name
505      */
506     static native byte[] getpwuid(int uid) throws UnixException;
507 
508     /**
509      * struct group *getgrgid(gid_t gid);
510      *
511      * @return  group->gr_name
512      */
513     static native byte[] getgrgid(int gid) throws UnixException;
514 
515     /**
516      * struct passwd *getpwnam(const char *name);
517      *
518      * @return  passwd->pw_uid
519      */
520     static int getpwnam(String name) throws UnixException {
521         NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
522         try {
523             return getpwnam0(buffer.address());
524         } finally {
525             buffer.release();
526         }
527     }
528     private static native int getpwnam0(long nameAddress) throws UnixException;
529 
530     /**
531      * struct group *getgrnam(const char *name);
532      *
533      * @return  group->gr_name
534      */
535     static int getgrnam(String name) throws UnixException {
536         NativeBuffer buffer = NativeBuffers.asNativeBuffer(Util.toBytes(name));
537         try {
538             return getgrnam0(buffer.address());
539         } finally {
540             buffer.release();
541         }
542     }
543     private static native int getgrnam0(long nameAddress) throws UnixException;
544 
545     /**
546      * statvfs(const char* path, struct statvfs *buf)
547      */
548     static void statvfs(UnixPath path, UnixFileStoreAttributes attrs)
549         throws UnixException
550     {
551         NativeBuffer buffer = copyToNativeBuffer(path);
552         try {
553             statvfs0(buffer.address(), attrs);
554         } finally {
555             buffer.release();
556         }
557     }
558     private static native void statvfs0(long pathAddress, UnixFileStoreAttributes attrs)
559         throws UnixException;
560 
561     /**
562      * char* strerror(int errnum)
563      */
564     static native byte[] strerror(int errnum);
565 
566     /**
567      * ssize_t fgetxattr(int filedes, const char *name, void *value, size_t size);
568      */
569     static int fgetxattr(int filedes, byte[] name, long valueAddress,
570                          int valueLen) throws UnixException
571     {
572         try (NativeBuffer buffer = NativeBuffers.asNativeBuffer(name)) {
573             return fgetxattr0(filedes, buffer.address(), valueAddress, valueLen);
574         }
575     }
576 
577     private static native int fgetxattr0(int filedes, long nameAddress,
578         long valueAddress, int valueLen) throws UnixException;
579 
580     /**
581      *  fsetxattr(int filedes, const char *name, const void *value, size_t size, int flags);
582      */
583     static void fsetxattr(int filedes, byte[] name, long valueAddress,
584                           int valueLen) throws UnixException
585     {
586         try (NativeBuffer buffer = NativeBuffers.asNativeBuffer(name)) {
587             fsetxattr0(filedes, buffer.address(), valueAddress, valueLen);
588         }
589     }
590 
591     private static native void fsetxattr0(int filedes, long nameAddress,
592         long valueAddress, int valueLen) throws UnixException;
593 
594     /**
595      * fremovexattr(int filedes, const char *name);
596      */
597     static void fremovexattr(int filedes, byte[] name) throws UnixException {
598         try (NativeBuffer buffer = NativeBuffers.asNativeBuffer(name)) {
599             fremovexattr0(filedes, buffer.address());
600         }
601     }
602 
603     private static native void fremovexattr0(int filedes, long nameAddress)
604         throws UnixException;
605 
606     /**
607      * size_t flistxattr(int filedes, const char *list, size_t size)
608      */
609     static native int flistxattr(int filedes, long listAddress, int size)
610         throws UnixException;
611 
612     /**
613      * Capabilities
614      */
615     private static final int SUPPORTS_OPENAT        = 1 << 1;  // syscalls
616     private static final int SUPPORTS_FUTIMES       = 1 << 2;
617     private static final int SUPPORTS_FUTIMENS      = 1 << 3;
618     private static final int SUPPORTS_LUTIMES       = 1 << 4;
619     private static final int SUPPORTS_XATTR         = 1 << 5;
620     private static final int SUPPORTS_BIRTHTIME     = 1 << 16; // other features
621     private static final int capabilities;
622 
623     /**
624      * Supports openat and other *at calls.
625      */
626     static boolean openatSupported() {
627         return (capabilities & SUPPORTS_OPENAT) != 0;
628     }
629 
630     /**
631      * Supports futimes or futimesat
632      */
633     static boolean futimesSupported() {
634         return (capabilities & SUPPORTS_FUTIMES) != 0;
635     }
636 
637     /**
638      * Supports futimens
639      */
640     static boolean futimensSupported() {
641         return (capabilities & SUPPORTS_FUTIMENS) != 0;
642     }
643 
644     /**
645      * Supports lutimes
646      */
647     static boolean lutimesSupported() {
648         return (capabilities & SUPPORTS_LUTIMES) != 0;
649     }
650 
651     /**
652      * Supports file birth (creation) time attribute
653      */
654     static boolean birthtimeSupported() {
655         return (capabilities & SUPPORTS_BIRTHTIME) != 0;
656     }
657 
658     /**
659      * Supports extended attributes
660      */
661     static boolean xattrSupported() {
662         return (capabilities & SUPPORTS_XATTR) != 0;
663     }
664 
665     private static native int init();
666     static {
667         jdk.internal.loader.BootLoader.loadLibrary("nio");
668         capabilities = init();
669     }
670 }