Пример #1
0
static int iterate_subdirs(const MEDIADB_DESCR_T *pMediaDb, const char *pathDb, 
                           const char *pathMedia, int level, unsigned int iterIdx) {
  DIR *pdir;
  FILE_LIST_T fileList;
  FILE_LIST_ENTRY_T *pFileListEntry;
  struct dirent *direntry;
  char bufMedia[VSX_MAX_PATH_LEN];
  char bufDb[VSX_MAX_PATH_LEN];
  char tmpfile[VSX_MAX_PATH_LEN];
  int rc = 0;
  int rcsub = 0;
  int fileListChanged = 0;
  int numTnCreated = 0;
  int highestTn;
  struct stat st;

//fprintf(stdout, "%d dir:'%s' '%s'\n", level, pathDb, pathMedia);

  //
  // TODO: escape invalid chars in pathnames ' , & # $ '
  // 

  if(level >= SRVMEDIA_MAX_LEVELS) {
    LOG(X_WARNING("Path '%s' exceeded max number of subdirs under %s"), 
        pathMedia, pMediaDb->mediaDir);
    return -1;
  }

  if(!(pdir = fileops_OpenDir(pathMedia))) {
    return -1;
  }

  memset(&fileList, 0, sizeof(fileList));
  file_list_read(pathDb, &fileList);
  strncpy(fileList.pathmedia, pathMedia, sizeof(fileList.pathmedia) - 1);


  while((direntry = fileops_ReadDir(pdir)) && g_proc_exit == 0) {
//fprintf(stdout, "- %d %s\n", level, direntry->d_name);
    if(direntry->d_type & DT_DIR) {

      if(mediadb_isvalidDirName(pMediaDb, direntry->d_name)) {

        if(mediadb_prepend_dir(pathDb, direntry->d_name, bufDb, sizeof(bufDb)) < 0) {
          LOG(X_WARNING("Unable to concatenate subdir %s %s"), bufDb, direntry->d_name);
        } else if(mediadb_prepend_dir(pathMedia, direntry->d_name, bufMedia, sizeof(bufMedia)) < 0) {
          LOG(X_WARNING("Unable to concatenate subdir %s %s"), bufMedia, direntry->d_name);
        } else {

          if(numTnCreated > 1) {
            file_list_write(pathDb, &fileList);
          }

          if((rcsub = iterate_subdirs(pMediaDb, bufDb, bufMedia, 
                                      level+1, iterIdx)) < 0) {
            rc = rcsub;
          }
          if(g_proc_exit != 0) {
            break;
          }

        }

      } else if(direntry->d_name[0] != '.') {
        //fprintf(stderr, "skipping directory '%s'\n", direntry->d_name);
      }

    } else if(mediadb_isvalidFileName(pMediaDb, direntry->d_name, 1, 0)) {

//fprintf(stdout, "%d media file %s '%s'\n", level, pathMedia, direntry->d_name);

      if(fileops_stat(pathDb, &st) != 0 && mediadb_mkdirfull(pMediaDb->dbDir, pathDb) < 0) {
        continue;
      } 

      if(mediadb_prepend_dir(pathDb, direntry->d_name, bufDb, sizeof(bufDb)) < 0) {
        LOG(X_ERROR("Unable to concatenate subdir %s %s"), bufDb, direntry->d_name);
        continue;
      } else if(mediadb_prepend_dir(pathMedia, direntry->d_name, bufMedia, sizeof(bufMedia)) < 0) {
        LOG(X_ERROR("Unable to concatenate subdir %s %s"), bufMedia, direntry->d_name);
        continue;
      }

      if(update_fileentry(&fileList, direntry->d_name, bufMedia, &pFileListEntry) > 0) {

        LOG(X_DEBUG("'%s' changed ('%s')"), direntry->d_name, pFileListEntry->name);

        fileListChanged = 1;
        if(pFileListEntry->numTn < 0) {
          pFileListEntry->numTn = 0;
        }

      }

      if(pMediaDb->avcthumb && pFileListEntry && pFileListEntry->vstr[0] != '\0' &&
         pFileListEntry->numTn != -1) {

        //
        // On very first iteration, check all thumbnails
        //
        snprintf(tmpfile, sizeof(tmpfile), "%s%s."NOTN_EXT, bufDb, pMediaDb->tn_suffix);

        if(fileops_stat(tmpfile, &st) == 0 && iterIdx > 0) {
          //  
          // Ignore thumbnail creation if the .notn file has been
          // previously created on an error condition
          //

        } else 
        //
        // Update thumbnail info
        //
        if((highestTn = createTn(pMediaDb, pFileListEntry, bufMedia, bufDb, 
            pFileListEntry->numTn, 1)) > pFileListEntry->numTn || highestTn == -1) {

          pFileListEntry->numTn = highestTn;
          fileListChanged = 1;

          // Periodically update the db file
          if(numTnCreated > 10) {
            file_list_write(pathDb, &fileList);
            numTnCreated = 0;
          }

        }

      }

    } else {
//fprintf(stdout, "skipping %s '%s'\n", pathMedia, direntry->d_name);
    }

  }

  fileops_CloseDir(pdir);

  if(g_proc_exit == 0) {

    if(file_list_removeunmarked(&fileList) || fileListChanged) {

       LOG(X_DEBUG("Writing file index in %s"), pathDb);
//fprintf(stdout, "level:%u\n", level);
      file_list_write(pathDb, &fileList);
    }

    //
    //Remove thumbnails which are not included in the fileList
    //
    clearTn(pathMedia, pathDb, &fileList);
  }

  file_list_close(&fileList);

  return rc;
}
Пример #2
0
DIR_ENTRY_LIST_T *direntry_getentries(const MEDIADB_DESCR_T *pMediaDb, 
                                      const char *dir, 
                                      const char *fidxdir, 
                                      const char *searchstr,
                                      int includedirs,
                                      unsigned int startidx,
                                      unsigned int max,
                                      enum DIR_SORT sort) {
  DIR *pdir;
  int rc = 0;
  struct dirent *direntry;
  char path[VSX_MAX_PATH_LEN];
  struct stat st;
  int addEntry;
  FILE_LIST_T fileList;
  FILE_LIST_ENTRY_T *pFileEntry = NULL;
  META_FILE_T metaFile;
  DIR_ENTRY_LIST_T *pEntryList = NULL;
  DIR_ENTRY_T entry;
  DIR_ENTRY_T *pEntry;
  const char *pdispname;
  unsigned int idx = 0;
  unsigned int cnt = 0;
  unsigned int cntInDir = 0;
  COMPARE_DIR_ENTRY compareFunc = direntry_getcompfunc(sort);

  VSX_DEBUG_MGR( LOG(X_DEBUG("MGR - direntry_getentries dir: '%s', fidxdir: '%s', searchstr: '%s', "
                             "includedirs: %d, startidx: %d, max: %d"), 
                            dir, fidxdir, searchstr, includedirs, startidx, max));

  if(!(pdir = fileops_OpenDir(dir))) {
    return NULL;
  }

  memset(&fileList, 0, sizeof(fileList));
  if(fidxdir) { 
    file_list_read(fidxdir, &fileList);
  }

  //
  // Read the directory wide metafile to get a list of 'ignore' entries
  //
  memset(&metaFile, 0, sizeof(metaFile));
  mediadb_prepend_dir(dir, METAFILE_DEFAULT, path, sizeof(path));
  if(fileops_stat(path, &st) == 0) {
    metafile_open(path, &metaFile, 1, 1);
  }

  while((direntry = fileops_ReadDir(pdir))) {

    VSX_DEBUG_MGR( LOG(X_DEBUGV("MGR - direntry_getentries d_name: '%s', isdir: %d"), 
           direntry->d_name, (direntry->d_type & DT_DIR)) );

    if(is_entry_ignored(metaFile.pignoreList, direntry->d_name)) {
      continue;
    }

    if(!(pdispname = find_entry_description(metaFile.pDescriptionList,
                                     direntry->d_name))) {
      pdispname = direntry->d_name;
    }

    if(searchstr && !is_match_search(pdispname, NULL, searchstr)) {
      continue;
    }

    memset(&entry, 0, sizeof(entry));
    strncpy(entry.d_name, direntry->d_name, sizeof(entry.d_name) - 1); 
    if(pdispname != direntry->d_name) {
      strncpy(entry.displayname, pdispname, sizeof(entry.displayname) - 1); 
    }
    entry.d_type = direntry->d_type;
    addEntry = 0;

    if(direntry->d_type & DT_DIR) {

      if(includedirs && mediadb_isvalidDirName(pMediaDb, direntry->d_name)) {
        addEntry = 1;
      }

    } else if(mediadb_isvalidFileName(pMediaDb, direntry->d_name, 1, 1)) {

      mediadb_prepend_dir(dir, direntry->d_name, path, sizeof(path));
      if(fileops_stat(path, &st) == 0) {
        entry.size = st.st_size;
        //entry.tm = st.st_mtime;
        entry.tm = st.st_ctime;

        if(fidxdir && (pFileEntry = file_list_find(&fileList, direntry->d_name))) {
          entry.numTn = pFileEntry->numTn; 
          entry.duration = pFileEntry->duration;
        }
        addEntry = 1;
      }

    }

    if(addEntry) {
      VSX_DEBUG_MGR( LOG(X_DEBUGV("MGR - direntry_getentries add d_name: '%s', isdir: %d"), 
           direntry->d_name, (direntry->d_type & DT_DIR)) );

      if(compareFunc || (idx >= startidx && (max == 0 || cnt < max))) {

        if(cnt >= DIR_ENTRY_LIST_BUFNUM) {
          LOG(X_WARNING("Not showing more than %d entries in %s"), cnt, dir);
          break;
        } else if(!(pEntry = direntry_addsorted(&pEntryList, &entry, compareFunc))) {
          LOG(X_ERROR("Failed to add directory entry '%s' to list"), direntry->d_name);
          rc = -1;
          break;
        }
        cnt++;
      }

      idx++;
      cntInDir++;
    }

  }

  //
  // Since when a sort is requested we have to sort every entry in the directory.  Now we can move the head pointer
  // to the first desired entry
  //
  if(pEntryList && compareFunc && startidx > 0) {
    pEntry = pEntryList->pHead;
    for(idx = 0; idx < startidx; idx++) {
      pEntry = pEntry->pnext;
      cnt--;
    }
    pEntryList->pHead = pEntry;
    if(cnt > max) {
      cnt = max;
    }
    //fprintf(stderr, "moved phead to %s, cnt:%d, cntInDir:%d\n", pEntryList->pHead ? pEntryList->pHead->d_name : NULL, cnt, cntInDir);
  }
  

  fileops_CloseDir(pdir);
  if(fidxdir) {
    file_list_close(&fileList);
  }
  metafile_close(&metaFile);

  if(rc == 0 && !pEntryList) {
    // If the user requested an index out of bounds, return an empty list with
    // a valid cntTotalInDir
    pEntryList = (DIR_ENTRY_LIST_T *) avc_calloc(1, sizeof(DIR_ENTRY_LIST_T));
  }

  if(pEntryList) {
    pEntryList->cntTotal = cnt; 
    pEntryList->cntTotalInDir = cntInDir; 
  }

  //if(pEntryList) fprintf(stderr, "DIR '%s' num:%d numAlloc:%d pnext:0x%x TOTAL:%d/%d\n", dir, pEntryList->num, pEntryList->numAlloc, pEntryList->pnext, pEntryList->cntTotal, pEntryList->cntTotalInDir);
 
  return pEntryList;
}