X-Git-Url: http://git.tuebingen.mpg.de/?p=paraslash.git;a=blobdiff_plain;f=aft.c;h=acf751566c61d82e23cc34565c1189f2db147917;hp=0e86b12d6c13ea1992c0c751dae61df43f78b226;hb=741c19c2a25c5d9e165cb99f7ff512209b7bade6;hpb=bb92402464a61c03616ff23397e753a9dca98d6d diff --git a/aft.c b/aft.c index 0e86b12d..acf75156 100644 --- a/aft.c +++ b/aft.c @@ -293,60 +293,36 @@ static struct osl_table_description audio_file_table_desc = { .column_descriptions = aft_cols }; -/* We don't want dot or dot-dot anywhere. */ -static int verify_dotfile(const char *rest) -{ - /* - * The first character was '.', but that has already been discarded, we - * now test the rest. - */ - switch (*rest) { - case '\0': case '/': /* /foo/. and /foo/./bar are not ok */ - return -1; - case '.': /* path start with /foo/.. */ - if (rest[1] == '\0' || rest[1] == '/') - return -1; /* /foo/.. or /foo/../bar are not ok */ - /* /foo/..bar is ok */ - } - return 1; -} - /* - * We fundamentally don't like some paths: We don't want double slashes or - * slashes at the end that can make pathnames ambiguous. + * Produce a canonicalized absolute pathname. + * + * Returns one if the resolved path a directory, zero if it is a regular file, + * negative on errors. */ static int verify_path(const char *orig_path, char **resolved_path) { - char c; - size_t len; - char *path; + int ret; + char *path = NULL; + struct stat statbuf; if (*orig_path != '/') /* we only accept absolute paths */ - return -E_BAD_PATH; - len = strlen(orig_path); - *resolved_path = para_strdup(orig_path); - path = *resolved_path; - while (len > 1 && path[--len] == '/') - path[len] = '\0'; /* remove slash at the end */ - c = *path++; - while (c) { - if (c == '/') { - c = *path++; - switch (c) { - case '/': /* double slash */ - goto bad_path; - case '.': - if (verify_dotfile(path) < 0) - goto bad_path; - default: - continue; - } - } - c = *path++; - } - return 1; -bad_path: - free(*resolved_path); + goto fail; + path = realpath(orig_path, NULL); + if (!path) + goto fail; + if (stat(path, &statbuf) < 0) + goto fail; + if (S_ISREG(statbuf.st_mode)) + ret = 0; + else if (S_ISDIR(statbuf.st_mode)) + ret = 1; + else + goto fail; + *resolved_path = path; + return ret; +fail: + *resolved_path = NULL; + free(path); return -E_BAD_PATH; } @@ -693,16 +669,13 @@ err: int load_afd(int shmid, struct audio_file_data *afd) { void *shm_afd; - char *buf; int ret; ret = shm_attach(shmid, ATTACH_RO, &shm_afd); if (ret < 0) return ret; *afd = *(struct audio_file_data *)shm_afd; - buf = shm_afd; - buf += sizeof(*afd); - load_chunk_table(&afd->afhi, buf); + load_chunk_table(&afd->afhi, shm_afd + sizeof(*afd)); shm_detach(shm_afd); return 1; } @@ -1043,6 +1016,28 @@ out: static struct ls_data status_item_ls_data; static struct osl_row *current_aft_row; +static void make_inode_status_items(struct para_buffer *pb) +{ + struct stat statbuf = {.st_size = 0}; + char *path, mtime_str[30] = "\0"; + struct tm mtime_tm; + int ret; + + ret = get_audio_file_path_of_row(current_aft_row, &path); + if (ret < 0) + goto out; + ret = stat(path, &statbuf); + if (ret < 0) + goto out; + localtime_r(&statbuf.st_mtime, &mtime_tm); + ret = strftime(mtime_str, 29, "%b %d %Y", &mtime_tm); + assert(ret > 0); /* number of bytes placed in mtime_str */ +out: + /* We don't care too much about errors here */ + (void)WRITE_STATUS_ITEM(pb, SI_MTIME, "%s\n", mtime_str); + (void)WRITE_STATUS_ITEM(pb, SI_FILE_SIZE, "%ld\n", statbuf.st_size / 1024); +} + static int make_status_items(void) { struct ls_options opts = { @@ -1057,6 +1052,7 @@ static int make_status_items(void) ret = print_list_item(&status_item_ls_data, &opts, &pb, current_time); if (ret < 0) return ret; + make_inode_status_items(&pb); free(status_items); status_items = pb.buf; memset(&pb, 0, sizeof(pb)); @@ -1068,6 +1064,7 @@ static int make_status_items(void) status_items = NULL; return ret; } + make_inode_status_items(&pb); free(parser_friendly_status_items); parser_friendly_status_items = pb.buf; return 1; @@ -1121,13 +1118,13 @@ again: return ret; ret = mmap_full_file(d->path, O_RDONLY, &map.data, &map.size, &afd->fd); if (ret < 0) - goto err; + goto out; hash_function(map.data, map.size, file_hash); ret = hash_compare(file_hash, d->hash); para_munmap(map.data, map.size); if (ret) { ret = -E_HASH_MISMATCH; - goto err; + goto out; } new_afsi = d->afsi; new_afsi.num_played++; @@ -1144,7 +1141,7 @@ again: */ afs_event(AFSI_CHANGE, NULL, &aced); ret = save_afd(afd); -err: +out: free(afd->afhi.chunk_table); osl_close_disk_object(&chunk_table_obj); if (ret < 0) { @@ -1957,7 +1954,6 @@ int com_add(struct command_context *cc) { int i, ret; struct private_add_data pad = {.cc = cc, .flags = 0}; - struct stat statbuf; for (i = 1; i < cc->argc; i++) { const char *arg = cc->argv[i]; @@ -1996,20 +1992,10 @@ int com_add(struct command_context *cc) return ret; continue; } - ret = stat(path, &statbuf); - if (ret < 0) { - ret = send_sb_va(&cc->scc, SBD_ERROR_LOG, - "failed to stat %s (%s)\n", path, - strerror(errno)); - free(path); - if (ret < 0) - return ret; - continue; - } - if (S_ISDIR(statbuf.st_mode)) + if (ret == 1) /* directory */ ret = for_each_file_in_dir(path, add_one_audio_file, &pad); - else + else /* regular file */ ret = add_one_audio_file(path, &pad); if (ret < 0) { send_sb_va(&cc->scc, SBD_OUTPUT, "%s: %s\n", path, @@ -2114,7 +2100,10 @@ static void com_touch_callback(int fd, const struct osl_object *query) struct touch_action_data tad = {.cto = query->data, .pb = { .max_size = shm_get_shmmax(), - .private_data = &fd, + .private_data = &(struct afs_max_size_handler_data) { + .fd = fd, + .band = SBD_OUTPUT + }, .max_size_handler = afs_max_size_handler } }; @@ -2255,7 +2244,10 @@ static void com_rm_callback(int fd, const struct osl_object *query) struct com_rm_action_data crd = {.flags = *(uint32_t *)query->data, .pb = { .max_size = shm_get_shmmax(), - .private_data = &fd, + .private_data = &(struct afs_max_size_handler_data) { + .fd = fd, + .band = SBD_OUTPUT + }, .max_size_handler = afs_max_size_handler } }; @@ -2397,7 +2389,10 @@ static void com_cpsi_callback(int fd, const struct osl_object *query) .flags = *(unsigned *)query->data, .pb = { .max_size = shm_get_shmmax(), - .private_data = &fd, + .private_data = &(struct afs_max_size_handler_data) { + .fd = fd, + .band = SBD_OUTPUT + }, .max_size_handler = afs_max_size_handler } };