Project

General

Profile

RE: Move existing recordings to new subdirectories ยป dvr_inotify.patch.diff

Joe User, 2019-11-26 12:52

View differences:

src/dvr/dvr_inotify.c
29 29
#define EVENT_SIZE    (sizeof(struct inotify_event))
30 30
#define EVENT_BUF_LEN (5 * EVENT_SIZE + NAME_MAX)
31 31
#define EVENT_MASK    IN_DELETE    | IN_DELETE_SELF | \
32
                      IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO
32
                      IN_MOVE_SELF | IN_MOVED_FROM | IN_MOVED_TO | \
33
                      IN_CREATE
33 34
                      
34 35
static int                         _inot_fd;
35 36
static RB_HEAD(,dvr_inotify_entry) _inot_tree;
......
44 45
{
45 46
  RB_ENTRY(dvr_inotify_entry) link;
46 47
  char *path;
47
  int fd;
48
  int wd;
49
  int parent_wd;
48 50
  LIST_HEAD(, dvr_inotify_filename) entries;
49 51
} dvr_inotify_entry_t;
50 52

  
......
102 104
/**
103 105
 * Add an entry for monitoring
104 106
 */
105
static void dvr_inotify_add_one ( dvr_entry_t *de, htsmsg_t *m )
107
//static void dvr_inotify_add_one ( dvr_entry_t *de, htsmsg_t *m )
108
static void dvr_inotify_add_one ( dvr_entry_t *de, int fd, const char *filename )
106 109
{
107 110
  dvr_inotify_filename_t *dif;
108 111
  dvr_inotify_entry_t *e;
109
  const char *filename;
112
//  const char *filename;
110 113
  char path[PATH_MAX];
111
  int fd = atomic_get(&_inot_fd);
112

  
113
  filename = htsmsg_get_str(m, "filename");
114
  if (filename == NULL || fd < 0)
115
    return;
116

  
114
//  int fd = atomic_get(&_inot_fd);
115
  char *dir = NULL;
116
  int len, append = 0;
117

  
118
//  filename = htsmsg_get_str(m, "filename");
119
//  if (filename == NULL || fd < 0)
120
//    return;
121

  
122
  dir = tvh_strdupa(filename);
123
  // check for newly created dir
124
  if((len = strlen(filename)) > 5 && !strcmp(filename + len - 5, "dummy")) {
125
    append = 1;
126
    dir = dirname(dir);
127
    tvherror(LS_DVR_INOTIFY, "add inotify watch for newly created directory \"%s\" ", dir);
128
  }
129
    
117 130
  /* Since filename might be inside a symlinked directory
118 131
   * we want to get the true name otherwise when we move
119 132
   * a file we will not match correctly since some files
120 133
   * may point to /mnt/a/z.ts and some to /mnt/b/z.ts
121 134
   */
122
  if (!realpath(filename, path))
135
  if (!realpath(dir, path)) {
136
    tvhwarn(LS_DVR_INOTIFY, "failed to add inotify watch for \"%s\" (err=%s)", filename,strerror(errno));
123 137
    return;
138
  }
139

  
140
  // append dummmy filename which will be stripped by dirname, leaving new dir path
141
  if(append)
142
    strcat(path, "/dummy.ts");
124 143

  
125 144
  SKEL_ALLOC(dvr_inotify_entry_skel);
126 145
  dvr_inotify_entry_skel->path = dirname(path);
127 146
  
128 147
  e = RB_INSERT_SORTED(&_inot_tree, dvr_inotify_entry_skel, link, _str_cmp);
129
  if (!e) {
148
  if (e) {
149
    SKEL_FREE(dvr_inotify_entry_skel);
150
    if (dvr_inotify_exists(e, de))
151
      return;
152
  } else {
130 153
    e       = dvr_inotify_entry_skel;
131 154
    SKEL_USED(dvr_inotify_entry_skel);
132 155
    e->path = strdup(e->path);
133
    e->fd   = inotify_add_watch(fd, e->path, EVENT_MASK);
156
    e->wd   = inotify_add_watch(fd, e->path, EVENT_MASK);
134 157
  }
135 158

  
136
  if (!dvr_inotify_exists(e, de)) {
159
//  if (!dvr_inotify_exists(e, de)) {
137 160

  
138 161
    dif = malloc(sizeof(*dif));
139 162
    dif->de = de;
140 163

  
141 164
    LIST_INSERT_HEAD(&e->entries, dif, link);
142 165

  
143
    if (e->fd < 0) {
144
      tvherror(LS_DVR, "failed to add inotify watch to %s (err=%s)",
166
    if (e->wd < 0) {
167
      tvherror(LS_DVR, "failed to add inotify watch for \"%s\" (err=%s)",
145 168
               e->path, strerror(errno));
146 169
      dvr_inotify_del(de);
147 170
    } else {
148
      tvhdebug(LS_DVR, "adding inotify watch to %s (fd=%d)",
149
               e->path, e->fd);
171
      tvhdebug(LS_DVR, "adding inotify watch for \"%s\" (wd=%d)",
172
               e->path, e->wd);
150 173
    }
151 174

  
152
  }
175
//  }
153 176
}
154 177

  
155 178
void dvr_inotify_add ( dvr_entry_t *de )
156 179
{
157 180
  htsmsg_field_t *f;
158 181
  htsmsg_t *m;
182
  const char *filename;
183
//  char path[PATH_MAX];
184
  int fd = atomic_get(&_inot_fd);
159 185

  
160
  if (atomic_get(&_inot_fd) < 0 || de->de_files == NULL)
186
  if (fd < 0 || de->de_files == NULL)
161 187
    return;
162 188

  
163
  HTSMSG_FOREACH(f, de->de_files)
164
    if ((m = htsmsg_field_get_map(f)) != NULL)
165
      dvr_inotify_add_one(de, m);
189
  HTSMSG_FOREACH(f, de->de_files) {
190
    if ((m = htsmsg_field_get_map(f)) != NULL) {
191
      filename = htsmsg_get_str(m, "filename");
192
      if (filename == NULL)
193
        continue;
194
      dvr_inotify_add_one(de, fd, filename);
195
      }
196
    }
166 197
}
167 198

  
168 199
/*
......
186 217
        if (LIST_FIRST(&e->entries) == NULL) {
187 218
          RB_REMOVE(&_inot_tree, e, link);
188 219
          fd = atomic_get(&_inot_fd);
189
          if (e->fd >= 0 && fd >= 0)
190
            inotify_rm_watch(fd, e->fd);
220
          if (e->wd >= 0 && fd >= 0)
221
            inotify_rm_watch(fd, e->wd);
191 222
          free(e->path);
192 223
          free(e);
193 224
        }
......
216 247
 */
217 248
static dvr_inotify_entry_t *
218 249
_dvr_inotify_find
219
  ( int fd )
250
  ( int wd )
220 251
{
221 252
  dvr_inotify_entry_t *e = NULL;
222 253
  RB_FOREACH(e, &_inot_tree, link)
223
    if (e->fd == fd)
254
    if (e->wd == wd)
224 255
      break;
225 256
  return e;
226 257
}
......
230 261
 */
231 262
static void
232 263
_dvr_inotify_moved
233
  ( int from_fd, const char *from, const char *to, int to_fd )
264
  ( int from_wd, const char *from, const char *to, int to_wd )
234 265
{
235 266
  dvr_inotify_filename_t *dif;
236 267
  dvr_inotify_entry_t *die;
......
242 273
  char realdir[PATH_MAX];
243 274
  char new_path[PATH_MAX+PATH_MAX+1];
244 275
  char ubuf[UUID_HEX_SIZE];
245
  char *file, *dir = NULL;
276
  char *file = NULL, *dir = NULL;
246 277

  
247
  if (!(die = _dvr_inotify_find(from_fd)))
278
  if (!(die = _dvr_inotify_find(from_wd)))
248 279
    return;
249 280

  
250 281
  snprintf(path, sizeof(path), "%s/%s", die->path, from);
251
  tvhdebug(LS_DVR, "inotify: moved from_fd: %d path: \"%s\" to: \"%s\" to_fd: %d", from_fd, path, to?:"<none>", to_fd);
282
  tvhdebug(LS_DVR, "inotify: moved from_wd: %d path: \"%s\" to: \"%s\" to_wd: %d", from_wd, path, to?:"<none>", to_wd);
252 283

  
253 284
  de = NULL;
254 285
  LIST_FOREACH(dif, &die->entries, link) {
......
295 326
    /* "to" will be NULL on a delete */
296 327
    if (to) {
297 328
      /* If we have moved to another directory we are inotify watching
298
       * then we get an fd for the directory we are moving to which is
329
       * then we get a wd for the directory we are moving to which is
299 330
       * different to the one we are moving from. So fetch the
300 331
       * directory details for that.
301 332
       */
302
      if (to_fd != -1 && to_fd != from_fd) {
303
        if (!(die = _dvr_inotify_find(to_fd))) {
304
          tvhdebug(LS_DVR, "Failed to _dvr_inotify_find for fd: %d", to_fd);
333
      if (to_wd != -1 && to_wd != from_wd) {
334
        if (!(die = _dvr_inotify_find(to_wd))) {
335
          tvhdebug(LS_DVR, "Failed to _dvr_inotify_find for wd: %d", to_wd);
305 336
          return;
306 337
        }
307 338
      }
308 339
      snprintf(new_path, sizeof(path), "%s/%s", die->path, to);
309 340
      tvhdebug(LS_DVR, "inotify: moved from name: \"%s\" to: \"%s\" for \"%s\"", path, new_path, idnode_uuid_as_str(&de->de_id, ubuf));
310 341
      htsmsg_set_str(m, "filename", new_path);
342
//      dvr_inotify_add_one(de, m);
343
      dvr_inotify_del(de);
311 344
      idnode_changed(&de->de_id);
312 345
    } else {
313 346
      htsmsg_field_destroy(de->de_files, f);
......
326 359
 */
327 360
static void
328 361
_dvr_inotify_delete
329
  ( int fd, const char *path )
362
  ( int wd, const char *path )
330 363
{
331
  _dvr_inotify_moved(fd, path, NULL, -1);
364
  _dvr_inotify_moved(wd, path, NULL, -1);
332 365
}
333 366

  
334 367
/*
......
336 369
 */
337 370
static void
338 371
_dvr_inotify_moved_all
339
  ( int fd, const char *to )
372
  ( int wd, const char *to )
340 373
{
341 374
  dvr_inotify_filename_t *f;
342 375
  dvr_inotify_entry_t *die;
343 376
  dvr_entry_t *de;
377
  htsmsg_t *m = NULL;
378
  htsmsg_field_t *fld = NULL;
379
  const char *filename;
380
  char *file = NULL;
344 381

  
345
  if (!(die = _dvr_inotify_find(fd)))
382
  if (!(die = _dvr_inotify_find(wd)))
346 383
    return;
347 384

  
348 385
  while ((f = LIST_FIRST(&die->entries))) {
386
//    if (!f->de)
387
//    continue;
349 388
    de = f->de;
350
    htsp_dvr_entry_update(de);
351
    idnode_notify_changed(&de->de_id);
352
    dvr_inotify_del(de);
389
    HTSMSG_FOREACH(fld, de->de_files) {
390
      if ((m = htsmsg_field_get_map(fld)) != NULL) {
391
        filename = htsmsg_get_str(m, "filename");
392
        if (!filename)
393
          continue;
394
      }
395
      tvhdebug(LS_DVR, "inotify: moved from name: dddddddddddddddddd   \"%s\"", filename);
396
      file = basename(tvh_strdupa(filename));
397

  
398
      if (strcmp(file, "dummy") == 0) {
399
        tvhdebug(LS_DVR, "inotify: moved from name: dddddddddddddddddd dummy matched  \"%s\"", file);
400
        dvr_entry_destroy(de, 0);
401
        break;
402
      } else {
403
        htsp_dvr_entry_update(de);
404
        idnode_notify_changed(&de->de_id);
405
        dvr_inotify_del(de);
406
      }
407
    }
353 408
  }
354 409
}
355 410

  
......
358 413
 */
359 414
static void
360 415
_dvr_inotify_delete_all
361
  ( int fd )
416
  ( int wd )
417
{
418
  _dvr_inotify_moved_all(wd, NULL);
419
}
420

  
421
/*
422
 * Directory created
423
 */
424
static void
425
_dvr_inotify_create
426
  ( int wd, const char *dir )
362 427
{
363
  _dvr_inotify_moved_all(fd, NULL);
428
  dvr_entry_t *de = NULL; // dummy de needed to add new dir
429
  htsmsg_t *m,  *l = htsmsg_create_list();
430
  dvr_inotify_entry_t *die;
431
  char path[PATH_MAX];
432
  char title[PATH_MAX];
433

  
434
  if (!(die = _dvr_inotify_find(wd)))
435
    return;
436

  
437
  tvhdebug(LS_DVR_INOTIFY, "inotify: created new dir \"%s\" in path: \"%s\" ", dir, die->path);
438
  snprintf(path, sizeof(path), "%s/%s/", die->path, dir);
439
  snprintf(title, sizeof(title), "Dummy holder for %s", path);
440

  
441
  m = htsmsg_create_map();  // create temporary map for dir path
442
  strcat(path, "dummy");  // add dummy filename which will get stripped
443
  htsmsg_set_str(m, "filename", path);
444
  htsmsg_add_msg(l, NULL, m);
445

  
446
  de = dvr_entry_create(NULL, NULL, 0);
447
  de->de_files = htsmsg_copy(l);
448
  lang_str_set(&de->de_title, title, "eng");
449
  m = htsmsg_create_map();  // create temporary map for dir path
450
  htsmsg_set_str(m, "filename", path);
451

  
452
  //dvr_inotify_add_one (de, m);
453
  dvr_inotify_add (de);
364 454
}
365 455

  
366 456
/*
......
371 461
  int fd, i, len;
372 462
  char buf[EVENT_BUF_LEN];
373 463
  const char *from;
374
  int fromfd;
464
  int fromwd;
375 465
  int cookie;
376 466
  struct inotify_event *ev;
377 467
  char from_prev[NAME_MAX + 1] = "";
378
  int fromfd_prev = 0;
468
  int fromwd_prev = 0;
379 469
  int cookie_prev = 0;
380 470

  
381 471
  while (tvheadend_is_running()) {
382 472

  
383 473
    /* Read events */
384
    fromfd = 0;
474
    fromwd = 0;
385 475
    cookie = 0;
386 476
    from   = NULL;
387 477
    i      = 0;
......
396 486
    tvh_mutex_lock(&global_lock);
397 487
    while (i < len) {
398 488
      ev = (struct inotify_event *)&buf[i];
399
      tvhtrace(LS_DVR_INOTIFY, "i=%d len=%d name=%s", i, len, ev->name);
489
      tvhtrace(LS_DVR_INOTIFY, "index=%d read_length=%d watch_descriptor=%d", i, len, ev->wd);
400 490
      i += EVENT_SIZE + ev->len;
401 491
      if (i > len)
402 492
        break;
......
404 494
      /* Moved */
405 495
      if (ev->mask & IN_MOVED_FROM) {
406 496
        from   = ev->name;
407
        fromfd = ev->wd;
497
        fromwd = ev->wd;
408 498
        cookie = ev->cookie;
409
        tvhtrace(LS_DVR_INOTIFY, "i=%d len=%d from=%s cookie=%d ", i, len, from, cookie);
499
        tvhtrace(LS_DVR_INOTIFY, "IN_MOVED_FROM \"%s\" cookie=%d ", from, cookie);
500
        if (ev->mask & IN_ISDIR)
501
          tvhtrace(LS_DVR_INOTIFY, "IN_ISDIR \"%s\"", ev->name);
410 502
        continue;
411 503

  
412 504
      } else if (ev->mask & IN_MOVED_TO) {
413
        tvhtrace(LS_DVR_INOTIFY, "i=%d len=%d to_cookie=%d from_cookie=%d cookie_prev=%d", i, len, ev->cookie, cookie, cookie_prev);
505
        tvhtrace(LS_DVR_INOTIFY, "IN_MOVED_TO \"%s\" to_cookie=%d from_cookie=%d cookie_prev=%d", ev->name, ev->cookie, cookie, cookie_prev);
506
        if (ev->mask & IN_ISDIR)
507
          tvhtrace(LS_DVR_INOTIFY, "IN_ISDIR \"%s\"", ev->name);
414 508
          if (from && ev->cookie == cookie) {
415
            _dvr_inotify_moved(fromfd, from, ev->name, ev->wd);
509
            _dvr_inotify_moved(fromwd, from, ev->name, ev->wd);
416 510
            from = NULL;
417 511
	    cookie = 0;
418 512
          } else if (from_prev[0] != '\0' && ev->cookie == cookie_prev) {
419
             _dvr_inotify_moved(fromfd_prev, from_prev, ev->name, ev->wd);
513
             _dvr_inotify_moved(fromwd_prev, from_prev, ev->name, ev->wd);
420 514
             from_prev[0] = '\0';
421 515
	     cookie_prev = 0;
422 516
	  }
423 517

  
424 518
      /* Removed */
425 519
      } else if (ev->mask & IN_DELETE) {
520
        tvhtrace(LS_DVR_INOTIFY, "IN_DELETE \"%s\"", ev->name);
426 521
        _dvr_inotify_delete(ev->wd, ev->name);
427
    
522

  
428 523
      /* Moved self */
429 524
      } else if (ev->mask & IN_MOVE_SELF) {
525
        tvhtrace(LS_DVR_INOTIFY, "IN_MOVE_SELF watch_descriptor=%d", ev->wd);
430 526
        _dvr_inotify_moved_all(ev->wd, NULL);
431
    
527

  
432 528
      /* Removed self */
433 529
      } else if (ev->mask & IN_DELETE_SELF) {
530
        tvhtrace(LS_DVR_INOTIFY, "IN_DELETE_SELF watch_descriptor=%d", ev->wd);
434 531
        _dvr_inotify_delete_all(ev->wd);
532

  
533
      /* Create directory */
534
      } else if (ev->mask & IN_CREATE) {
535
        tvhtrace(LS_DVR_INOTIFY, "IN_CREATE \"%s\"", ev->name);
536
       if (ev->mask & IN_ISDIR) {
537
         tvhtrace(LS_DVR_INOTIFY, "IN_ISDIR \"%s\"", ev->name);
538
        _dvr_inotify_create(ev->wd,ev->name);
539
       }
540

  
541
      /* Watch removed */
542
      } else if (ev->mask & IN_IGNORED) {
543
        tvhtrace(LS_DVR_INOTIFY, "IN_IGNORED watch_descriptor=%d", ev->wd);
435 544
      }
545

  
546
      else tvhwarn(LS_DVR_INOTIFY, "NO matching flags for \"%s\" watch_descriptor=%d", ev->name, ev->wd);
436 547
    }
437 548
    // if still old "from", assume matching "to" is not coming
438 549
    if (from_prev[0] != '\0') {
439
      _dvr_inotify_moved(fromfd_prev, from_prev, NULL, -1);
550
      _dvr_inotify_moved(fromwd_prev, from_prev, NULL, -1);
440 551
      from_prev[0] = '\0';
441 552
      cookie_prev = 0;
442 553
    }
443 554
    // if unmatched "from", save in case matching "to" is coming in next read
444 555
    if (from) {
445 556
      strcpy(from_prev, from);
446
      fromfd_prev = fromfd;
557
      fromwd_prev = fromwd;
447 558
      cookie_prev = cookie;
448
      tvhdebug(LS_DVR_INOTIFY, "i=%d len=%d cookie_prev=%d from_prev=%s fd=%d EOR", i, len, cookie_prev, from_prev, fromfd_prev);
559
      tvhtrace(LS_DVR_INOTIFY, "i=%d len=%d cookie_prev=%d from_prev=\"%s\" wd=%d EOR", i, len, cookie_prev, from_prev, fromwd_prev);
449 560
    }
450 561
    tvh_mutex_unlock(&global_lock);
451 562
  }
    (1-1/1)