Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

ps3: Add NTFS support

  • Loading branch information...
commit 7ffd6046d7ae7b3c18654e037cebd1439236d265 1 parent 5d8f667
Andreas Öman authored
3  .gitmodules
@@ -7,3 +7,6 @@
7 7
 [submodule "ext/xmp"]
8 8
 	path = ext/xmp
9 9
 	url = git://github.com/andoma/xmp
  10
+[submodule "ext/libntfs_ext"]
  11
+	path = ext/libntfs_ext
  12
+	url = https://github.com/andoma/libntfs_ext.git
48  Makefile
@@ -177,6 +177,8 @@ SRCS += src/fileaccess/fileaccess.c \
177 177
 	src/fileaccess/fa_imageloader.c \
178 178
 	src/fileaccess/fa_indexer.c \
179 179
 
  180
+
  181
+
180 182
 SRCS += src/fileaccess/fa_ftp.c \
181 183
 	src/fileaccess/ftpparse.c \
182 184
 
@@ -193,6 +195,7 @@ SRCS-$(CONFIG_LIBGME)          += src/fileaccess/fa_gmefile.c
193 195
 SRCS-$(CONFIG_LOCATEDB)        += src/fileaccess/fa_locatedb.c
194 196
 SRCS-$(CONFIG_SPOTLIGHT)       += src/fileaccess/fa_spotlight.c
195 197
 SRCS-$(CONFIG_READAHEAD_CACHE) += src/fileaccess/fa_cache.c
  198
+SRCS-$(CONFIG_LIBNTFS)         += src/fileaccess/fa_ntfs.c
196 199
 
197 200
 SRCS += ext/audio/sid.c
198 201
 
@@ -607,6 +610,51 @@ CFLAGS_com += -Iext/polarssl-1.2.0/include
607 610
 endif
608 611
 
609 612
 ##############################################################
  613
+# 
  614
+##############################################################
  615
+
  616
+SRCS-$(CONFIG_LIBNTFS) += \
  617
+	ext/libntfs_ext/source/acls.c \
  618
+	ext/libntfs_ext/source/attrib.c \
  619
+	ext/libntfs_ext/source/attrlist.c \
  620
+	ext/libntfs_ext/source/bitmap.c \
  621
+	ext/libntfs_ext/source/bootsect.c \
  622
+	ext/libntfs_ext/source/cache.c \
  623
+	ext/libntfs_ext/source/cache2.c \
  624
+	ext/libntfs_ext/source/collate.c \
  625
+	ext/libntfs_ext/source/compress.c \
  626
+	ext/libntfs_ext/source/debug.c \
  627
+	ext/libntfs_ext/source/device.c \
  628
+	ext/libntfs_ext/source/device_io.c \
  629
+	ext/libntfs_ext/source/dir.c \
  630
+	ext/libntfs_ext/source/efs.c \
  631
+	ext/libntfs_ext/source/gekko_io.c \
  632
+	ext/libntfs_ext/source/index.c \
  633
+	ext/libntfs_ext/source/inode.c \
  634
+	ext/libntfs_ext/source/lcnalloc.c \
  635
+	ext/libntfs_ext/source/logfile.c \
  636
+	ext/libntfs_ext/source/logging.c \
  637
+	ext/libntfs_ext/source/mft.c \
  638
+	ext/libntfs_ext/source/misc.c \
  639
+	ext/libntfs_ext/source/mst.c \
  640
+	ext/libntfs_ext/source/ntfs.c \
  641
+	ext/libntfs_ext/source/ntfsdir.c \
  642
+	ext/libntfs_ext/source/ntfsfile.c \
  643
+	ext/libntfs_ext/source/ntfsinternal.c \
  644
+	ext/libntfs_ext/source/object_id.c \
  645
+	ext/libntfs_ext/source/realpath.c \
  646
+	ext/libntfs_ext/source/reparse.c \
  647
+	ext/libntfs_ext/source/runlist.c \
  648
+	ext/libntfs_ext/source/security.c \
  649
+	ext/libntfs_ext/source/unistr.c \
  650
+	ext/libntfs_ext/source/volume.c \
  651
+	ext/libntfs_ext/source/xattrs.c \
  652
+
  653
+${BUILDDIR}/ext/libntfs_ext/source/%.o : CFLAGS = -Wall ${OPTFLAGS} \
  654
+	-DHAVE_CONFIG_H -Iext/libntfs_ext/source -Iext/libntfs_ext/include \
  655
+	-DPS3_GEKKO
  656
+
  657
+##############################################################
610 658
 # TLSF (Two Level Segregated Fit) memory allocator
611 659
 ##############################################################
612 660
 
3  configure.ps3
@@ -70,6 +70,9 @@ rtmpdump_setup
70 70
 xmp_setup
71 71
 bzip2_setup
72 72
 
  73
+enable libntfs
  74
+update_ext_submodule libntfs_ext
  75
+
73 76
 cat >> ${CONFIG_MAK} <<EOF
74 77
 CFLAGS_cfg += -mminimal-toc -DWORDS_BIGENDIAN
75 78
 CFLAGS_cfg += -DPATH_MAX=512 -DPS3
1  ext/libntfs_ext
... ...
@@ -0,0 +1 @@
  1
+Subproject commit 11e7bab659f8c1529751060e7aacb15759dd9bcb
419  src/fileaccess/fa_ntfs.c
... ...
@@ -0,0 +1,419 @@
  1
+/*
  2
+ *  Native FTP client
  3
+ *  Copyright (C) 2013 Andreas Öman
  4
+ *
  5
+ *  This program is free software: you can redistribute it and/or modify
  6
+ *  it under the terms of the GNU General Public License as published by
  7
+ *  the Free Software Foundation, either version 3 of the License, or
  8
+ *  (at your option) any later version.
  9
+ *
  10
+ *  This program is distributed in the hope that it will be useful,
  11
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
  12
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  13
+ *  GNU General Public License for more details.
  14
+ *
  15
+ *  You should have received a copy of the GNU General Public License
  16
+ *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
  17
+ */
  18
+
  19
+#include <stdio.h>
  20
+#include <arpa/inet.h>
  21
+#include <assert.h>
  22
+
  23
+#include "showtime.h"
  24
+#include "fileaccess.h"
  25
+#include "fa_proto.h"
  26
+#include "misc/callout.h"
  27
+#include "service.h"
  28
+
  29
+#include "ext/libntfs_ext/include/ntfs.h"
  30
+#include "ext/libntfs_ext/source/logging.h"
  31
+
  32
+
  33
+
  34
+typedef struct fs_handle {
  35
+  fa_handle_t h;
  36
+  int fd;
  37
+} fs_handle_t;
  38
+
  39
+static void
  40
+fs_urlsnprintf(char *buf, size_t bufsize, const char *prefix, const char *base,
  41
+	       const char *fname)
  42
+{
  43
+  int blen = strlen(base);
  44
+  if(!strcmp(base, "/"))
  45
+    base = "";
  46
+
  47
+  snprintf(buf, bufsize, "%s%s%s%s", prefix, base,
  48
+	   blen > 0 && base[blen - 1] == '/' ? "" : "/", fname);
  49
+}
  50
+
  51
+
  52
+/**
  53
+ *
  54
+ */
  55
+static int
  56
+ntfs_scandir(fa_protocol_t *fap, fa_dir_t *fd,
  57
+	     const char *url, char *errbuf, size_t errlen)
  58
+{
  59
+  DIR_ITER *di = ps3ntfs_diropen(url);
  60
+  char filename[1024];
  61
+  char buf[URL_MAX];
  62
+  struct stat st;
  63
+  int type;
  64
+
  65
+  while(1) {
  66
+    if(ps3ntfs_dirnext(di, filename, &st))
  67
+      break;
  68
+    
  69
+  switch(st.st_mode & S_IFMT) {
  70
+    case S_IFDIR:
  71
+      type = CONTENT_DIR;
  72
+      break;
  73
+
  74
+    case S_IFREG:
  75
+      type = CONTENT_FILE;
  76
+      break;
  77
+
  78
+    default:
  79
+      continue;
  80
+    }
  81
+
  82
+    fs_urlsnprintf(buf, sizeof(buf), "", url, filename);
  83
+    fa_dir_add(fd, buf, filename, type);
  84
+  }
  85
+  ps3ntfs_dirclose(di);
  86
+  return 0;
  87
+}
  88
+
  89
+
  90
+/**
  91
+ *
  92
+ */
  93
+static fa_handle_t *
  94
+ntfs_open(struct fa_protocol *fap, const char *url,
  95
+         char *errbuf, size_t errsize, int flags,
  96
+         struct prop *stats)
  97
+{
  98
+  int fd;
  99
+
  100
+  if(flags & FA_WRITE) {
  101
+
  102
+    int open_flags = O_RDWR | O_CREAT;
  103
+
  104
+    if(!(flags & FA_APPEND))
  105
+      open_flags |= O_TRUNC;
  106
+
  107
+    fd = ps3ntfs_open(url, open_flags, 0666);
  108
+
  109
+    if(fd >= 0 && (flags & FA_APPEND))
  110
+      ps3ntfs_seek64(fd, 0, SEEK_END);
  111
+
  112
+  } else {
  113
+    fd = ps3ntfs_open(url, O_RDONLY, 0);
  114
+  }
  115
+
  116
+  if(fd == -1) {
  117
+    snprintf(errbuf, errsize, "%s", strerror(ps3ntfs_errno()));
  118
+    return NULL;
  119
+  }
  120
+  fs_handle_t *fh = calloc(1, sizeof(fs_handle_t));
  121
+  fh->fd = fd;
  122
+  fh->h.fh_proto = fap;
  123
+  return &fh->h;
  124
+}
  125
+
  126
+
  127
+/**
  128
+ *
  129
+ */
  130
+static void
  131
+ntfs_close(fa_handle_t *fh0)
  132
+{
  133
+  fs_handle_t *fh = (fs_handle_t *)fh0;
  134
+  ps3ntfs_close(fh->fd);
  135
+  free(fh);
  136
+
  137
+}
  138
+
  139
+
  140
+/**
  141
+ * Read from file. Same semantics as POSIX read(2)
  142
+ */
  143
+static int
  144
+ntfs_read(fa_handle_t *fh0, void *buf, size_t size0)
  145
+{
  146
+  fs_handle_t *fh = (fs_handle_t *)fh0;
  147
+  return ps3ntfs_read(fh->fd, buf, size0);
  148
+}
  149
+
  150
+
  151
+
  152
+/**
  153
+ *
  154
+ */
  155
+static int
  156
+ntfs_write(fa_handle_t *fh0, const void *buf, size_t size0)
  157
+{
  158
+  fs_handle_t *fh = (fs_handle_t *)fh0;
  159
+  return ps3ntfs_write(fh->fd, buf, size0);
  160
+}
  161
+
  162
+
  163
+/**
  164
+ * Seek in file. Same semantics as POSIX lseek(2)
  165
+ */
  166
+static int64_t
  167
+ntfs_seek(fa_handle_t *fh0, int64_t pos, int whence)
  168
+{
  169
+  fs_handle_t *fh = (fs_handle_t *)fh0;
  170
+  return ps3ntfs_seek64(fh->fd, pos, whence);
  171
+}
  172
+
  173
+
  174
+/**
  175
+ * Return size of file
  176
+ */
  177
+static int64_t
  178
+ntfs_fsize(fa_handle_t *fh0)
  179
+{
  180
+  fs_handle_t *fh = (fs_handle_t *)fh0;
  181
+  struct stat st;
  182
+  ps3ntfs_fstat(fh->fd, &st);
  183
+  return st.st_size;
  184
+}
  185
+
  186
+/**
  187
+ * stat(2) file
  188
+ *
  189
+ * If non_interactive is set, this is probe request and it must not
  190
+ * ask for any user input (access credentials, etc)
  191
+ */
  192
+static int
  193
+ntfs_stat(struct fa_protocol *fap, const char *url, struct fa_stat *fs,
  194
+	  char *errbuf, size_t errsize, int non_interactive)
  195
+{
  196
+  struct stat st;
  197
+  if(ps3ntfs_stat(url, &st)) {
  198
+    snprintf(errbuf, errsize, "No such file");
  199
+    return FAP_STAT_ERR;
  200
+  }
  201
+  memset(fs, 0, sizeof(struct fa_stat));
  202
+  fs->fs_size = st.st_size;
  203
+  fs->fs_mtime = st.st_mtime;
  204
+  fs->fs_type = S_ISDIR(st.st_mode) ? CONTENT_DIR : CONTENT_FILE;
  205
+  return 0;
  206
+}
  207
+
  208
+static int
  209
+ntfs_unlink(const fa_protocol_t *fap, const char *url,
  210
+	    char *errbuf, size_t errlen)
  211
+{
  212
+  if(ps3ntfs_unlink(url)) {
  213
+    snprintf(errbuf, errlen, "%s", strerror(ps3ntfs_errno()));
  214
+    return -1;
  215
+  }
  216
+  return 0;
  217
+}
  218
+
  219
+
  220
+/**
  221
+ * Rmdir (remove directory)
  222
+ */
  223
+static int
  224
+ntfs_rmdir(const fa_protocol_t *fap, const char *url, char *errbuf, size_t errlen)
  225
+{
  226
+  return ntfs_unlink(fap, url, errbuf, errlen);
  227
+}
  228
+
  229
+/**
  230
+ *
  231
+ */
  232
+static int
  233
+ntfs_rename(const fa_protocol_t *fap, const char *old, const char *new,
  234
+	    char *errbuf, size_t errlen)
  235
+{
  236
+  if(ps3ntfs_rename(old, new)) {
  237
+    snprintf(errbuf, errlen, "%s", strerror(ps3ntfs_errno()));
  238
+    return -1;
  239
+  }
  240
+  return 0;
  241
+}
  242
+
  243
+
  244
+/**
  245
+ *
  246
+ */
  247
+static int
  248
+ntfs_makedirs(struct fa_protocol *fap, const char *url,
  249
+	      char *errbuf, size_t errlen)
  250
+{
  251
+  if(ps3ntfs_mkdir(url, 0777)) {
  252
+    snprintf(errbuf, errlen, "%s", strerror(ps3ntfs_errno()));
  253
+    return -1;
  254
+  }
  255
+  return 0;
  256
+}
  257
+
  258
+
  259
+
  260
+static callout_t ntfs_callout;
  261
+
  262
+typedef struct ntfs_dev {
  263
+  char inserted;
  264
+  char hold_counter;
  265
+  int partitions_mounted;
  266
+  ntfs_md *mounts;
  267
+  service_t **services;
  268
+} ntfs_dev_t;
  269
+
  270
+static ntfs_dev_t ntfs_devs[8];
  271
+
  272
+static const DISC_INTERFACE *disc_ntfs[8]= {
  273
+    &__io_ntfs_usb000,
  274
+    &__io_ntfs_usb001,
  275
+    &__io_ntfs_usb002,
  276
+    &__io_ntfs_usb003,
  277
+    &__io_ntfs_usb004,
  278
+    &__io_ntfs_usb005,
  279
+    &__io_ntfs_usb006,
  280
+    &__io_ntfs_usb007
  281
+};
  282
+
  283
+/**
  284
+ *
  285
+ */
  286
+static void
  287
+ntfs_periodic(struct callout *c, void *opaque)
  288
+{
  289
+  for(int i = 0; i < 8; i++) {
  290
+    int r = PS3_NTFS_IsInserted(i);
  291
+    ntfs_dev_t *d = &ntfs_devs[i];
  292
+
  293
+    if(!r) {
  294
+      if(!d->inserted)
  295
+	continue;
  296
+
  297
+      d->inserted = 0;
  298
+
  299
+      if(d->partitions_mounted) {
  300
+	for(int j = 0; j < d->partitions_mounted; j++) {
  301
+	  if(d->mounts[j].name[0]) {
  302
+	    TRACE(TRACE_DEBUG, "NTFS", "Unmounting %s", d->mounts[j].name);
  303
+	    ntfsUnmount(d->mounts[j].name, 1);
  304
+	  }
  305
+	}
  306
+
  307
+	free(d->mounts);
  308
+	d->mounts = NULL;
  309
+
  310
+	for(int j = 0; j < d->partitions_mounted; j++)
  311
+	  service_destroy(d->services[j]);
  312
+
  313
+	free(d->services);
  314
+	d->services = NULL;
  315
+
  316
+	d->partitions_mounted = 0;
  317
+      }
  318
+      continue;
  319
+    }
  320
+
  321
+    if(d->inserted == 2)
  322
+      continue;
  323
+
  324
+    d->inserted = 1;
  325
+    if(d->hold_counter < 5) {
  326
+      d->hold_counter++;
  327
+      TRACE(TRACE_DEBUG, "NTFS", "Waiting for device %d to settle", i);
  328
+      continue;
  329
+    }
  330
+
  331
+
  332
+    d->inserted = 2;
  333
+    d->partitions_mounted =
  334
+      ntfsMountDevice(disc_ntfs[i], &d->mounts, NTFS_DEFAULT | NTFS_RECOVER);
  335
+
  336
+    TRACE(TRACE_DEBUG, "NTFS", "Mounted %d partitions on device %d",
  337
+	  d->partitions_mounted, i);
  338
+
  339
+    d->services = malloc(sizeof(service_t *) * d->partitions_mounted);
  340
+
  341
+    for(int j = 0; j < d->partitions_mounted; j++) {
  342
+      TRACE(TRACE_DEBUG, "NTFS", "Mounted %s", d->mounts[j].name);
  343
+      char url[64];
  344
+      snprintf(url, sizeof(url), "%s://", d->mounts[j].name);
  345
+      d->services[j] = service_create_managed(url, d->mounts[j].name,
  346
+					      url, "usb", NULL, 0, 1, 
  347
+					      SVC_ORIGIN_MEDIA, 1);
  348
+    }
  349
+  }
  350
+  callout_arm(&ntfs_callout, ntfs_periodic, NULL, 1);
  351
+}
  352
+
  353
+
  354
+static int
  355
+ntfs_log(const char *function, const char *file, int line,
  356
+	u32 level, void *data, const char *format, va_list args)
  357
+{
  358
+  char buf[1024];
  359
+  vsnprintf(buf, sizeof(buf), format, args);
  360
+  trace(TRACE_NO_PROP, TRACE_DEBUG, "NTFS", "[%x]: %s: %s:%d %s",
  361
+	hts_thread_current(),
  362
+	function, file, line, buf);
  363
+  return 0;
  364
+}
  365
+
  366
+
  367
+/**
  368
+ *
  369
+ */
  370
+static void
  371
+ntfs_init(void)
  372
+{
  373
+  extern void ntfsInit(void);
  374
+
  375
+  ntfsInit();
  376
+  if(0) {
  377
+    ntfs_log_set_levels(-1);
  378
+    ntfs_log_set_handler(ntfs_log);
  379
+  } else {
  380
+    ntfs_log_clear_levels(-1);
  381
+  }
  382
+  callout_arm(&ntfs_callout, ntfs_periodic, NULL, 1);
  383
+}
  384
+
  385
+
  386
+/**
  387
+ *
  388
+ */
  389
+static int
  390
+ntfs_match_proto(const char *str)
  391
+{
  392
+  if(strncmp(str, "ntfs", 4))
  393
+    return 1;
  394
+  return !(str[4] >= '0' && str[4] <= '8');
  395
+}
  396
+
  397
+/**
  398
+ * Main NTFS protocol dispatch
  399
+ */
  400
+static fa_protocol_t fa_protocol_ntfs = {
  401
+  .fap_flags = FAP_INCLUDE_PROTO_IN_URL,
  402
+  .fap_init  = ntfs_init,
  403
+  .fap_match_proto = ntfs_match_proto,
  404
+  .fap_scan  = ntfs_scandir,
  405
+  .fap_open  = ntfs_open,
  406
+  .fap_close = ntfs_close,
  407
+  .fap_read  = ntfs_read,
  408
+  .fap_write = ntfs_write,
  409
+  .fap_seek  = ntfs_seek,
  410
+  .fap_fsize = ntfs_fsize,
  411
+  .fap_stat  = ntfs_stat,
  412
+  .fap_unlink= ntfs_unlink,
  413
+  .fap_rmdir = ntfs_rmdir,
  414
+  .fap_rename = ntfs_rename,
  415
+  .fap_makedirs = ntfs_makedirs,
  416
+
  417
+
  418
+};
  419
+FAP_REGISTER(ntfs);
5  src/fileaccess/fa_proto.h
@@ -50,6 +50,11 @@ typedef struct fa_protocol {
50 50
   const char *fap_name;
51 51
 
52 52
   /**
  53
+   * If set, it will superseed fap_name. Return 0 for match
  54
+   */
  55
+  int (*fap_match_proto)(const char *prefix);
  56
+
  57
+  /**
53 58
    * Directory scan url for files. 
54 59
    */
55 60
   int (*fap_scan)(struct fa_protocol *fap, fa_dir_t *fa, const char *url,
11  src/fileaccess/fileaccess.c
@@ -133,8 +133,15 @@ fa_resolve_proto(const char *url, fa_protocol_t **p,
133 133
   hts_mutex_lock(&fap_mutex);
134 134
 
135 135
   LIST_FOREACH(fap, &fileaccess_all_protocols, fap_link) {
136  
-    if(strcmp(fap->fap_name, buf))
137  
-      continue;
  136
+
  137
+    if(fap->fap_match_proto != NULL) {
  138
+      if(fap->fap_match_proto(buf))
  139
+	continue;
  140
+    } else {
  141
+      if(strcmp(fap->fap_name, buf))
  142
+	continue;
  143
+    }
  144
+
138 145
     *p = fap;
139 146
     fap_retain(fap);
140 147
     hts_mutex_unlock(&fap_mutex);
1  support/configure.inc
@@ -87,6 +87,7 @@ CONFIG_LIST="
87 87
  bughunt
88 88
  bspatch
89 89
  connman
  90
+ libntfs
90 91
 "
91 92
 
92 93
 cleanup() {

Git Notes

changelog

ps3: Add support for NTFS devices connected over USB

Not thoroughly tested yet, feedback is welcome

0 notes on commit 7ffd604

Please sign in to comment.
Something went wrong with that request. Please try again.