H:
H: Options:
H:
+H: -a Add all files. The default is to add only files ending in a known suffix
+H: for a supported audio format.
+H:
H: -l Add files lazily. If a file already exists in the database, skip this file.
H: This operation is really cheap. Use it when adding large directories if only a
H: few files where added.
H:
H: -sy: sort by lyrics id.
H:
-H: -sb: sort by bitrate.
+H: -sb: sort by bit rate.
H:
H: -sd: sort by duration.
H:
#define ADD_FLAG_LAZY 1
#define ADD_FLAG_FORCE 2
#define ADD_FLAG_VERBOSE 4
+#define ADD_FLAG_ALL 8
/* TODO: change log messages so that they get written to the result buffer */
ret = verify_path(arg, &path);
if (ret < 0)
goto out_free;
+ ret = guess_audio_format(path);
+ if (ret < 0 && !(pad->flags & ADD_FLAG_ALL)) {
+ if (pad->flags & ADD_FLAG_VERBOSE)
+ ret = send_va_buffer(pad->fd, "%s: %s\n",
+ PARA_STRERROR(-ret), path);
+ ret = 1;
+ goto out_free;
+ }
query.data = path;
query.size = strlen(path) + 1;
ret = send_callback_request(path_brother_callback, &query, &result);
format_num = ret;
afhi_ptr = &afhi;
}
- if (pad->flags & ADD_FLAG_VERBOSE)
- send_va_buffer(pad->fd, "adding %s\n", path);
+ if (pad->flags & ADD_FLAG_VERBOSE) {
+ ret = send_va_buffer(pad->fd, "adding %s\n", path);
+ if (ret < 0)
+ goto out_unmap;
+ }
munmap(map.data, map.size);
save_audio_file_info(hash, path, afhi_ptr, pad->flags, format_num, &obj);
/* Ask afs to consider this entry for adding. */
out_unmap:
munmap(map.data, map.size);
out_free:
- if (ret < 0)
+ if (ret < 0 && ret != -E_SEND)
send_va_buffer(pad->fd, "failed to add %s (%s)\n", path?
path : arg, PARA_STRERROR(-ret));
free(obj.data);
free(path);
if (afhi_ptr)
free(afhi_ptr->chunk_table);
- return 1; /* it's not an error if not all files could be added */
+ /* it's not an error if not all files could be added */
+ return ret == -E_SEND? ret : 1;
}
int com_add(int fd, int argc, char * const * const argv)
i++;
break;
}
+ if (!strcmp(arg, "-a")) {
+ pad.flags |= ADD_FLAG_ALL;
+ continue;
+ }
if (!strcmp(arg, "-l")) {
pad.flags |= ADD_FLAG_LAZY;
continue;
if (ret < 0)
PARA_NOTICE_LOG("failed to stat %s (%s)", path,
strerror(errno));
- else
+ else {
if (S_ISDIR(statbuf.st_mode))
- for_each_file_in_dir(path, add_one_audio_file,
+ ret = for_each_file_in_dir(path, add_one_audio_file,
&pad);
else
- add_one_audio_file(path, &pad);
+ ret = add_one_audio_file(path, &pad);
+ if (ret < 0) {
+ send_va_buffer(fd, "%s: %s\n", path, PARA_STRERROR(-ret));
+ free(path);
+ return ret;
+ }
+ }
free(path);
}
ret = 1;
#define VSS_ERRORS \
+ PARA_ERROR(BAD_AUDIO_FILE_SUFFIX, "unknown suffix"), \
PARA_ERROR(AUDIO_FORMAT, "audio format not recognized"), \
PARA_ERROR(CHUNK, "unable to get chunk"), \
PARA_ERROR(OPENDIR, "can not open directory"), \
PARA_ERROR(NOSPC, "no space left on device"), \
PARA_ERROR(OPEN, "failed to open file"), \
+ PARA_ERROR(CHDIR_PERM, "insufficient permissions to chdir"), \
#define WRITE_ERRORS \
break;
};
PARA_ERROR_LOG("failed to open %s: %s\n", path, strerror(errno));
- return ret;
+ return -E_OPEN;
+}
+
+/**
+ * Wrapper for chdir(2).
+ *
+ * \param path the specified directory.
+ *
+ * \return Positive on success, negative on errors.
+ */
+int para_chdir(const char *path)
+{
+ int ret = chdir(path);
+
+ if (ret >= 0)
+ return 1;
+ switch (errno) {
+ case ENOENT:
+ return -E_NOENT;
+ case EACCES:
+ return -E_CHDIR_PERM;
+ };
+ return -E_CHDIR;
}
/**
return ret;
*cwd = ret;
}
- ret = -E_CHDIR;
- if (chdir(dirname) < 0)
+ ret = para_chdir(dirname);
+ if (ret < 0)
goto close_cwd;
ret = -E_OPENDIR;
*dir = opendir(".");
int para_opendir(const char *dirname, DIR **dir, int *cwd);
int para_mkdir(const char *path, mode_t mode);
int para_fchdir(int fd);
+int para_chdir(const char *path);
* \param func The function to call for each entry.
* \param private_data Pointer to an arbitrary data structure.
*
- * For each regular file in \a dirname, the supplied function \a func is
+ * For each regular file under \a dirname, the supplied function \a func is
* called. The full path of the regular file and the \a private_data pointer
- * are passed to \a func.
+ * are passed to \a func. Directories for which the calling process has no
+ * permissions to change to are silently ignored.
*
* \return On success, 1 is returned. Otherwise, this function returns a
* negative value which indicates the kind of the error.
int cwd_fd, ret2, ret = para_opendir(dirname, &dir, &cwd_fd);
if (ret < 0)
- return ret;
+ return ret == -E_CHDIR_PERM? 1 : ret;
/* scan cwd recursively */
while ((entry = readdir(dir))) {
mode_t m;
return i;
}
}
- return -1;
+ return -E_BAD_AUDIO_FILE_SUFFIX;
}
static int get_audio_format(int omit)