/* * Removes an entry from a directory. */ PUBLIC int dir_remove(struct inode *dinode, const char *filename) { struct buffer *buf; /* Block buffer. */ struct d_dirent *d; /* Directory entry. */ struct inode *file; /* File inode. */ d = dirent_search(dinode, filename, &buf, 0); /* Not found. */ if (d == NULL) return (-ENOENT); /* Cannot remove '.' */ if (d->d_ino == dinode->num) { brelse(buf); return (-EBUSY); } file = inode_get(dinode->dev, d->d_ino); /* Failed to get file's inode. */ if (file == NULL) { brelse(buf); return (-ENOENT); } /* Unlinking directory. */ if (S_ISDIR(file->mode)) { /* Not allowed. */ if (!IS_SUPERUSER(curr_proc)) { inode_put(file); brelse(buf); return (-EPERM); } /* Directory not empty. */ if (dinode->size) { inode_put(file); brelse(buf); return (-EBUSY); } } /* Remove directory entry. */ d->d_ino = INODE_NULL; buf->flags |= BUFFER_DIRTY; inode_touch(dinode); file->nlinks--; inode_touch(file); inode_put(file); brelse(buf); return (0); }
/** * @brief Searches for a file in a directory. * * @details Searches for a file named @p filename in the directory poitned to * by @p dinode. * * @param ip Inode where the file that shall be searched. * @param filename Name of the file that shall be searched. * * @returns If the requested file exists in the directory, than its inode number * is returned. However, if the file does not exist #INODE_NULL is * is returns instead. * * @note @p ip must be locked. * @note @p filename must point to a valid location. */ PUBLIC ino_t dir_search(struct inode *ip, const char *filename) { struct buffer *buf; /* Block buffer. */ struct d_dirent *d; /* Directory entry. */ /* Search directory entry. */ d = dirent_search(ip, filename, &buf, 0); if (d == NULL) return (INODE_NULL); brelse(buf); return (d->d_ino); }
int vpbp_dclose(SceUID fd) { int result; struct IoDirentEntry *entry; lock(); entry = dirent_search(fd); if (entry != NULL && strlen(entry->path) > 4 && 0 == stricmp(entry->path+4, "/PSP/GAME")) { save_cache(); } result = sceIoDclose(fd); unlock(); return result; }
/* * Adds an entry to a directory. */ PUBLIC int dir_add(struct inode *dinode, struct inode *inode, const char *name) { struct buffer *buf; /* Block buffer. */ struct d_dirent *d; /* Disk directory entry. */ d = dirent_search(dinode, name, &buf, 1); /* Failed to create directory entry. */ if (d == NULL) return (-1); kstrncpy(d->d_name, name, NAME_MAX); d->d_ino = inode->num; buf->flags |= BUFFER_DIRTY; brelse(buf); return (0); }
int vpbp_dread(SceUID fd, SceIoDirent * dir) { int result, cur_idx, ret; struct IoDirentEntry *entry; lock(); entry = dirent_search(fd); if(entry == NULL) { result = -44; goto exit; } result = sceIoDread(entry->iso_dfd, dir); if(sceKernelFindModuleByName("Game_Categories_Light") == NULL) { while(result > 0 && !is_iso(dir)) { result = sceIoDread(entry->iso_dfd, dir); } } if (result > 0 && is_iso(dir)) { VirtualPBP *vpbp; vpbp = vpbp_realloc(g_vpbps, g_vpbps_cnt+1); if(vpbp == NULL) { result = -42; goto exit; } g_vpbps = vpbp; g_vpbps_cnt++; cur_idx = g_vpbps_cnt-1; vpbp = &g_vpbps[cur_idx]; STRCPY_S(vpbp->name, entry->path); vpbp->name[4] = '\0'; STRCAT_S(vpbp->name, "/ISO"); STRCAT_S(vpbp->name, entry->path + sizeof("xxx:/PSP/GAME") - 1); STRCAT_S(vpbp->name, "/"); STRCAT_S(vpbp->name, dir->d_name); memcpy(&vpbp->ctime, &dir->d_stat.st_ctime, sizeof(vpbp->ctime)); memcpy(&vpbp->mtime, &dir->d_stat.st_mtime, sizeof(vpbp->mtime)); ret = get_cache(vpbp->name, &vpbp->mtime, vpbp); if (ret < 0) { ret = build_vpbp(vpbp); if (ret < 0) { result = -43; goto exit; } } result = add_fake_dirent(dir, cur_idx); } exit: unlock(); return result; }