natFilePosix.cc 7.56 KB
Newer Older
1
// natFile.cc - Native part of File class for POSIX.
Tom Tromey committed
2

3
/* Copyright (C) 1998, 1999, 2000, 2001, 2002, 2003  Free Software Foundation
Tom Tromey committed
4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26

   This file is part of libgcj.

This software is copyrighted work licensed under the terms of the
Libgcj License.  Please consult the file "LIBGCJ_LICENSE" for
details.  */

#include <config.h>

#include <stdio.h>
#include <errno.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <stdlib.h>
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#include <string.h>
27
#include <utime.h>
Tom Tromey committed
28

Tom Tromey committed
29
#include <gcj/cni.h>
Tom Tromey committed
30 31 32
#include <jvm.h>
#include <java/io/File.h>
#include <java/io/IOException.h>
33
#include <java/util/ArrayList.h>
Tom Tromey committed
34 35
#include <java/lang/String.h>
#include <java/io/FilenameFilter.h>
36
#include <java/io/FileFilter.h>
Tom Tromey committed
37 38 39
#include <java/lang/System.h>

jboolean
40
java::io::File::_access (jint query)
Tom Tromey committed
41
{
42
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
43
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
Tom Tromey committed
44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60
  buf[total] = '\0';
  JvAssert (query == READ || query == WRITE || query == EXISTS);
#ifdef HAVE_ACCESS
  int mode;
  if (query == READ)
    mode = R_OK;
  else if (query == WRITE)
    mode = W_OK;
  else
    mode = F_OK;
  return ::access (buf, mode) == 0;
#else
  return false;
#endif
}

jboolean
61
java::io::File::_stat (jint query)
Tom Tromey committed
62
{
63 64 65 66
  if (query == ISHIDDEN)
    return getName()->charAt(0) == '.';

#ifdef HAVE_STAT
67
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
68
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
Tom Tromey committed
69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
  buf[total] = '\0';

  struct stat sb;
  if (::stat (buf, &sb))
    return false;
  
  JvAssert (query == DIRECTORY || query == ISFILE);
  jboolean r = S_ISDIR (sb.st_mode);
  return query == DIRECTORY ? r : ! r;
#else
  return false;
#endif
}

jlong
84
java::io::File::attr (jint query)
Tom Tromey committed
85
{
86
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
87
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
Tom Tromey committed
88 89 90 91 92 93 94 95 96
  buf[total] = '\0';

#ifdef HAVE_STAT
  struct stat sb;
  // FIXME: not sure about return value here.
  if (::stat (buf, &sb))
    return 0;

  JvAssert (query == MODIFIED || query == LENGTH);
97
  return query == MODIFIED ? (jlong)sb.st_mtime * 1000 : sb.st_size;
Tom Tromey committed
98 99 100 101 102 103 104 105 106
#else
  // There's no good choice here.
  return 23;
#endif
}

jstring
java::io::File::getCanonicalPath (void)
{
107 108 109
  // We use `+2' here because we might need to use `.' for our special
  // case.
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 2);
110
  char buf2[MAXPATHLEN];
Tom Tromey committed
111
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
112 113 114 115 116

  // Special case: treat "" the same as ".".
  if (total == 0)
    buf[total++] = '.';

Tom Tromey committed
117 118 119 120
  buf[total] = '\0';

#ifdef HAVE_REALPATH
  if (realpath (buf, buf2) == NULL)
121
    throw new IOException (JvNewStringLatin1 (strerror (errno)));
Tom Tromey committed
122 123 124 125 126 127 128 129 130 131 132 133

  // FIXME: what encoding to assume for file names?  This affects many
  // calls.
  return JvNewStringUTF (buf2);
#else
  return JvNewStringUTF (buf);
#endif
}

jboolean
java::io::File::isAbsolute (void)
{
134
  return path->length() > 0 && path->charAt(0) == '/';
Tom Tromey committed
135 136
}

137 138 139 140
jobjectArray
java::io::File::performList (java::io::FilenameFilter *filter, 
			     java::io::FileFilter *fileFilter, 
			     java::lang::Class *result_type)
Tom Tromey committed
141
{
Anthony Green committed
142 143 144
  /* Some systems have dirent.h, but no directory reading functions like
     opendir.  */
#if defined(HAVE_DIRENT_H) && defined(HAVE_OPENDIR)
145
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
146
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
Tom Tromey committed
147 148 149 150 151 152
  buf[total] = '\0';

  DIR *dir = opendir (buf);
  if (! dir)
    return NULL;

153
  java::util::ArrayList *list = new java::util::ArrayList ();
154 155 156 157 158 159 160 161
  struct dirent *d;
#ifdef HAVE_READDIR_R
  int name_max = pathconf (buf, _PC_NAME_MAX);
  char dbuf[sizeof (struct dirent) + name_max + 1];
  while (readdir_r (dir, (struct dirent *) dbuf, &d) == 0 && d != NULL)
#else /* HAVE_READDIR_R */
  while ((d = readdir (dir)) != NULL)
#endif /* HAVE_READDIR_R */
Tom Tromey committed
162
    {
163 164 165 166
      // Omit "." and "..".
      if (d->d_name[0] == '.'
	  && (d->d_name[1] == '\0'
	      || (d->d_name[1] == '.' && d->d_name[2] == '\0')))
Tom Tromey committed
167 168 169 170 171
	continue;

      jstring name = JvNewStringUTF (d->d_name);
      if (filter && ! filter->accept(this, name))
	continue;
172

173 174 175 176 177 178 179 180 181 182
      if (result_type == &java::io::File::class$)
        {
	  java::io::File *file = new java::io::File (this, name);
	  if (fileFilter && ! fileFilter->accept(file))
	    continue;

	  list->add(file);
	}
      else
	list->add(name);
Tom Tromey committed
183 184 185 186
    }

  closedir (dir);

187 188 189
  jobjectArray ret = JvNewObjectArray (list->size(), result_type, NULL);
  list->toArray(ret);
  return ret;
Anthony Green committed
190
#else /* HAVE_DIRENT_H && HAVE_OPENDIR */
Tom Tromey committed
191
  return NULL;
Anthony Green committed
192
#endif /* HAVE_DIRENT_H && HAVE_OPENDIR */
Tom Tromey committed
193 194 195 196 197
}

jboolean
java::io::File::performMkdir (void)
{
198
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
Tom Tromey committed
199 200 201 202 203 204 205 206 207 208 209
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
  buf[total] = '\0';

#ifdef HAVE_MKDIR
  return ::mkdir (buf, 0755) == 0;
#else
  return false;
#endif
}

jboolean
210 211
java::io::File::performSetReadOnly (void)
{
212
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
213 214 215
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
  buf[total] = '\0';

216
#if defined (HAVE_STAT) && defined (HAVE_CHMOD)
217 218 219 220 221 222 223 224 225 226 227 228 229 230 231
  struct stat sb;
  if (::stat (buf, &sb))
    return false;

  if (::chmod(buf, sb.st_mode & 0555))
    return false;  
  return true;
#else
  return false;
#endif
}

JArray< ::java::io::File *>*
java::io::File::performListRoots ()
{
232 233 234 235 236
  ::java::io::File *f = new ::java::io::File (JvNewStringLatin1 ("/"));
  JArray<java::io::File *> *unixroot
    = reinterpret_cast <JArray<java::io::File *>*> 
          (JvNewObjectArray (1, &java::io::File::class$, f));
  elements (unixroot) [0] = f;
237 238 239 240
  return unixroot;
}

jboolean
Tom Tromey committed
241 242
java::io::File::performRenameTo (File *dest)
{
243
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
Tom Tromey committed
244 245
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
  buf[total] = '\0';
246 247
  char *buf2
    = (char *) __builtin_alloca (JvGetStringUTFLength (dest->path) + 1);
Tom Tromey committed
248 249 250 251 252 253 254 255 256 257 258
  total = JvGetStringUTFRegion (dest->path, 0, dest->path->length(), buf2);
  buf2[total] = '\0';

#ifdef HAVE_RENAME
  return ::rename (buf, buf2) == 0;
#else
  return false;
#endif
}

jboolean
259 260 261 262 263
java::io::File::performSetLastModified (jlong time)
{
#ifdef HAVE_UTIME
  utimbuf tb;

264
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
265 266 267 268 269 270 271 272 273 274 275 276 277 278
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
  buf[total] = '\0';
  
  tb.actime = time / 1000;
  tb.modtime = time / 1000;
  return ::utime (buf, &tb);
#else
  return false;
#endif
}

jboolean
java::io::File::performCreate (void)
{
279
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
  buf[total] = '\0';

  int fd = ::open (buf, O_CREAT | O_EXCL, 0644);

  if (fd < 0)
    {
      if (errno == EEXIST)
        return false;
      throw new IOException (JvNewStringLatin1 (strerror (errno)));
    }
  else
    {
      ::close (fd);
      return true;
    }
}

jboolean
java::io::File::performDelete (void)
Tom Tromey committed
300
{
301
  char *buf = (char *) __builtin_alloca (JvGetStringUTFLength (path) + 1);
302
  jsize total = JvGetStringUTFRegion (path, 0, path->length(), buf);
Tom Tromey committed
303 304 305 306 307 308 309
  buf[total] = '\0';

#ifdef HAVE_UNLINK
#ifdef HAVE_RMDIR
  if (! ::rmdir (buf))
    return true;
  if (errno == ENOTDIR)
310
#endif // HAVE_RMDIR
Tom Tromey committed
311 312 313 314
    return ::unlink (buf) == 0;
#endif // HAVE_UNLINK
  return false;
}
315 316 317 318 319 320 321

void
java::io::File::init_native ()
{
  maxPathLen = MAXPATHLEN;
  caseSensitive = true;
}